From 5ba9fde10ff918c9e691670380ebfa67e389b4e3 Mon Sep 17 00:00:00 2001 From: Gary Sharp Date: Tue, 8 Jul 2014 16:47:13 +1000 Subject: [PATCH] Feature #2: Improve Warranty Logging Warranty job UI changes to make consistent with plans for Repair Logging --- Disco.BI/BI/Extensions/JobActionExtensions.cs | 60 +- .../BIModelExtensions/PluginExtensions.cs | 18 +- Disco.Web/ClientSource/Style/Job.css | 16 + Disco.Web/ClientSource/Style/Job.less | 11 + Disco.Web/ClientSource/Style/Job.min.css | 2 +- Disco.Web/Controllers/JobController.cs | 50 +- Disco.Web/Models/Job/LogWarrantyModel.cs | 12 +- Disco.Web/Views/Job/JobParts/Warranty.cshtml | 211 ++++--- .../Views/Job/JobParts/Warranty.generated.cs | 573 ++++++++++-------- Disco.Web/Views/Job/LogWarranty.cshtml | 88 ++- Disco.Web/Views/Job/LogWarranty.generated.cs | 247 +++++--- Disco.Web/Views/Job/LogWarrantyError.cshtml | 41 +- .../Views/Job/LogWarrantyError.generated.cs | 141 +++-- 13 files changed, 933 insertions(+), 537 deletions(-) diff --git a/Disco.BI/BI/Extensions/JobActionExtensions.cs b/Disco.BI/BI/Extensions/JobActionExtensions.cs index 6bd1d4d3..da500cf6 100644 --- a/Disco.BI/BI/Extensions/JobActionExtensions.cs +++ b/Disco.BI/BI/Extensions/JobActionExtensions.cs @@ -8,6 +8,7 @@ using Disco.Services.Plugins; using Disco.Services.Plugins.Features.WarrantyProvider; using Disco.Services.Users; using Disco.Services.Authorization; +using Disco.Services.Plugins.Features.RepairProvider; namespace Disco.BI.Extensions { @@ -180,11 +181,34 @@ namespace Disco.BI.Extensions JobId = j.Id, TechUserId = TechUser.UserId, Timestamp = DateTime.Now, - Comments = string.Format("Warranty Claim Submitted{0}{0}Provider: {1}{0}Repair Address: {2}{0}Provider Reference: {3}{0}{0}{4}", Environment.NewLine, WarrantyProvider.Manifest.Name, Address.Name, providerRef, FaultDescription) + Comments = string.Format("####Warranty Claim Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n{3}", WarrantyProvider.Manifest.Name, Address.Name, providerRef, FaultDescription) }; Database.JobLogs.Add(jobLog); } } + public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, string CustomProviderName, string CustomProviderReference, OrganisationAddress Address, User TechUser) + { + if (!j.CanLogWarranty()) + throw new InvalidOperationException("Log Warranty was Denied"); + + j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now; + j.JobMetaWarranty.ExternalName = CustomProviderName; + + if (CustomProviderReference != null && CustomProviderReference.Length > 100) + j.JobMetaWarranty.ExternalReference = CustomProviderReference.Substring(0, 100); + else + j.JobMetaWarranty.ExternalReference = CustomProviderReference; + + // Write Log + JobLog jobLog = new JobLog() + { + 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) + }; + Database.JobLogs.Add(jobLog); + } #endregion #region Convert HWar to HNWar @@ -317,16 +341,38 @@ namespace Disco.BI.Extensions !j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue; } - public static void OnLogRepair(this Job j, string RepairerName, string RepairerReference) + public static void OnLogRepair(this Job j, DiscoDataContext Database, string RepairDescription, PluginFeatureManifest RepairProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary ProviderProperties) { if (!j.CanLogRepair()) throw new InvalidOperationException("Log Repair was Denied"); - if (j.JobMetaNonWarranty.RepairerName != RepairerName) - j.JobMetaNonWarranty.RepairerName = RepairerName; - if (j.JobMetaNonWarranty.RepairerReference != RepairerReference) - j.JobMetaNonWarranty.RepairerReference = RepairerReference; - j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now; + if (string.IsNullOrWhiteSpace(RepairDescription)) + RepairDescription = j.GenerateFaultDescriptionFooter(Database, RepairProviderDefinition); + else + RepairDescription = string.Concat(RepairDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, RepairProviderDefinition)); + + using (RepairProviderFeature RepairProvider = RepairProviderDefinition.CreateInstance()) + { + string providerRef = RepairProvider.SubmitJob(Database, j, Address, TechUser, RepairDescription, ProviderProperties); + + j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now; + j.JobMetaNonWarranty.RepairerName = RepairProvider.ProviderId; + + if (providerRef.Length > 100) + j.JobMetaNonWarranty.RepairerReference = providerRef.Substring(0, 100); + else + j.JobMetaNonWarranty.RepairerReference = providerRef; + + // Write Log + JobLog jobLog = new JobLog() + { + JobId = j.Id, + TechUserId = TechUser.UserId, + Timestamp = DateTime.Now, + Comments = string.Format("####Repair Request Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n{3}", RepairProvider.Manifest.Name, Address.Name, providerRef, RepairDescription) + }; + Database.JobLogs.Add(jobLog); + } } #endregion diff --git a/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs b/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs index a38d393e..90a7d223 100644 --- a/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs +++ b/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs @@ -16,16 +16,22 @@ namespace Disco.Web.Extensions if (SelectedItem != null) selectedId = SelectedItem.Id; - return PluginFeatureDefinitions.ToSelectListItems(selectedId); + return PluginFeatureDefinitions.ToSelectListItems(selectedId, false, null); } public static List ToSelectListItems(this IEnumerable PluginDefinitions, string SelectedId = null, bool IncludeInstructionFirst = false, string InstructionMessage = "Select a Plugin") { - var selectItems = default(List); - if (SelectedId == null) - selectItems = PluginDefinitions.Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name }).ToList(); - else - selectItems = PluginDefinitions.Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name, Selected = (SelectedId.Equals(wpd.Id)) }).ToList(); + return ToSelectListItems(PluginDefinitions, SelectedId, IncludeInstructionFirst, InstructionMessage, null); + } + + public static List ToSelectListItems(this IEnumerable PluginDefinitions, string SelectedId = null, bool IncludeInstructionFirst = false, string InstructionMessage = "Select a Plugin", Dictionary AdditionalItems = null) + { + List selectItems; + + 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 (IncludeInstructionFirst) selectItems.Insert(0, new SelectListItem() { Value = String.Empty, Text = String.Format("<{0}>", InstructionMessage), Selected = String.IsNullOrEmpty(SelectedId) }); diff --git a/Disco.Web/ClientSource/Style/Job.css b/Disco.Web/ClientSource/Style/Job.css index b47b921c..48380dc2 100644 --- a/Disco.Web/ClientSource/Style/Job.css +++ b/Disco.Web/ClientSource/Style/Job.css @@ -605,6 +605,22 @@ #jobComponents tr .totalCost { font-weight: bold; } +#jobWarrantyDetails { + border: solid 1px #d8d8d8; + border-collapse: collapse; +} +#jobWarrantyDetails td { + border: solid 1px #d8d8d8; + background-color: #ffffff; +} +#jobWarrantyDetails th { + background-color: #eeeeee; + border: solid 1px #d8d8d8; +} +#jobWarrantyDetails tr th { + width: 200px; + text-align: right; +} #jobNonWarrantyFinance { border: solid 1px #d8d8d8; border-collapse: collapse; diff --git a/Disco.Web/ClientSource/Style/Job.less b/Disco.Web/ClientSource/Style/Job.less index f720f537..ff68e370 100644 --- a/Disco.Web/ClientSource/Style/Job.less +++ b/Disco.Web/ClientSource/Style/Job.less @@ -645,6 +645,17 @@ } } +#jobWarrantyDetails { + .tableDataDark; + + tr { + th { + width: 200px; + text-align: right; + } + } +} + #jobNonWarrantyFinance { .tableDataDark; diff --git a/Disco.Web/ClientSource/Style/Job.min.css b/Disco.Web/ClientSource/Style/Job.min.css index e5d18b92..b625badf 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}#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}#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 eb6a1613..891e2f1a 100644 --- a/Disco.Web/Controllers/JobController.cs +++ b/Disco.Web/Controllers/JobController.cs @@ -397,7 +397,7 @@ namespace Disco.Web.Controllers { // Create New Job var currentUser = Database.Users.Find(UserService.CurrentUserId); - + // Try QuickLog? bool addAutoQueues = !(Authorization.Has(Claims.Job.Actions.Close) && m.QuickLog.HasValue && m.QuickLog.Value @@ -473,7 +473,12 @@ namespace Disco.Web.Controllers [DiscoAuthorize(Claims.Job.Actions.LogWarranty)] public virtual ActionResult LogWarranty(int id, string WarrantyProviderId, int? OrganisationAddressId) { - var m = new Models.Job.LogWarrantyModel() { JobId = id, WarrantyProviderId = WarrantyProviderId, OrganisationAddressId = OrganisationAddressId }; + var m = new Models.Job.LogWarrantyModel() + { + JobId = id, + WarrantyProviderId = WarrantyProviderId, + OrganisationAddressId = OrganisationAddressId + }; m.UpdateModel(Database, false); m.FaultDescription = m.Job.GenerateFaultDescription(Database); @@ -500,6 +505,47 @@ namespace Disco.Web.Controllers { switch (m.WarrantyAction) { + case "Update": + var updatedModel = new Models.Job.LogWarrantyModel() + { + JobId = m.JobId, + WarrantyProviderId = m.WarrantyProviderId, + OrganisationAddressId = m.OrganisationAddressId, + FaultDescription = m.FaultDescription + }; + updatedModel.UpdateModel(Database, false); + + if (updatedModel.WarrantyProvider != null) + { + using (var wp = updatedModel.WarrantyProvider.CreateInstance()) + { + if (wp.SubmitJobViewType != null) + { + updatedModel.WarrantyProviderSubmitJobViewType = wp.SubmitJobViewType; + updatedModel.WarrantyProviderSubmitJobModel = wp.SubmitJobViewModel(Database, this, updatedModel.Job, updatedModel.OrganisationAddress, updatedModel.TechUser); + } + } + } + + return View(updatedModel); + case "Custom": + if (string.IsNullOrWhiteSpace(m.CustomProviderName)) + { + ModelState.AddModelError("CustomProviderName", "The Custom 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); + Database.SaveChanges(); + return RedirectToAction(MVC.Job.Show(m.JobId)); + } + catch (Exception ex) + { + m.Error = ex; + return View(Views.LogWarrantyError, m); + throw; + } case "Disclose": using (var p = m.WarrantyProvider.CreateInstance()) { diff --git a/Disco.Web/Models/Job/LogWarrantyModel.cs b/Disco.Web/Models/Job/LogWarrantyModel.cs index ef9546f9..8dc61113 100644 --- a/Disco.Web/Models/Job/LogWarrantyModel.cs +++ b/Disco.Web/Models/Job/LogWarrantyModel.cs @@ -34,6 +34,16 @@ namespace Disco.Web.Models.Job [Required] public string WarrantyAction { get; set; } + public bool IsCustomProvider + { + get + { + return WarrantyProviderId == "CUSTOM"; + } + } + public string CustomProviderName { get; set; } + public string CustomProviderReference { get; set; } + public Type WarrantyProviderSubmitJobViewType { get; set; } public object WarrantyProviderSubmitJobModel { get; set; } public string WarrantyProviderPropertiesJson { get; set; } @@ -93,7 +103,7 @@ namespace Disco.Web.Models.Job WarrantyProviderId = Job.Device.DeviceModel.DefaultWarrantyProvider; } - if (!string.IsNullOrEmpty(WarrantyProviderId)) + if (!string.IsNullOrEmpty(WarrantyProviderId) && WarrantyProviderId != "CUSTOM") WarrantyProvider = Plugins.GetPluginFeature(WarrantyProviderId, typeof(WarrantyProviderFeature)); this.OrganisationAddresses = Database.DiscoConfiguration.OrganisationAddresses.Addresses.OrderBy(a => a.Name).ToList(); diff --git a/Disco.Web/Views/Job/JobParts/Warranty.cshtml b/Disco.Web/Views/Job/JobParts/Warranty.cshtml index e9e2ed93..86a57b47 100644 --- a/Disco.Web/Views/Job/JobParts/Warranty.cshtml +++ b/Disco.Web/Views/Job/JobParts/Warranty.cshtml @@ -3,106 +3,109 @@ Authorization.Require(Claims.Job.ShowWarranty); }
- - - - - - - - - - - - + + + + - - @if (Model.Job.JobMetaWarranty.ExternalLoggedDate.HasValue){ - - - - - } - @if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ProviderDetails)) - { - Html.BundleDeferred("~/ClientScripts/Modules/Disco-AjaxHelperIcons"); + { + if (string.IsNullOrWhiteSpace(Model.Job.JobMetaWarranty.ExternalReference)) + {<Unknown/None>} + else + {@Model.Job.JobMetaWarranty.ExternalReference} + } + + + if (Model.Job.JobMetaWarranty.ExternalLoggedDate.HasValue) + { + + + + + } + if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ProviderDetails)) + { + Html.BundleDeferred("~/ClientScripts/Modules/Disco-AjaxHelperIcons"); @@ -113,13 +116,31 @@ + + } + } + else + { + + + }
Warranty Provider - - @if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ExternalName)) - { - @Html.EditorFor(m => m.Job.JobMetaWarranty.ExternalName) - @AjaxHelpers.AjaxSave() - @AjaxHelpers.AjaxLoader() - - } - else - { - if (string.IsNullOrWhiteSpace(Model.Job.JobMetaWarranty.ExternalName)) - {<Unknown/None>} + }); + + } else - {@Model.Job.JobMetaWarranty.ExternalName} - } -
Warranty Logged - - @if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ExternalLoggedDate)) - { - @CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalLoggedDate, "Not Logged", "Job_JobMetaWarranty_ExternalLoggedDate") - @AjaxHelpers.AjaxLoader() - - } - else - { - @CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalLoggedDate, "Unknown/None", null) - } -
Warranty Reference - - @if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ExternalReference)) - { - @Html.EditorFor(m => m.Job.JobMetaWarranty.ExternalReference) - @AjaxHelpers.AjaxSave() - @AjaxHelpers.AjaxLoader() - + } + else + { + @CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalLoggedDate, "Unknown/None", null) + } +
Warranty Reference + + @if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ExternalReference)) + { + @Html.EditorFor(m => m.Job.JobMetaWarranty.ExternalReference) + @AjaxHelpers.AjaxSave() + @AjaxHelpers.AjaxLoader() + - } - else - { - if (string.IsNullOrWhiteSpace(Model.Job.JobMetaWarranty.ExternalReference)) - {<Unknown/None>} + }); + + } else - {@Model.Job.JobMetaWarranty.ExternalReference} - } -
Warranty Completed - - @if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ExternalCompletedDate)) - { - @CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalCompletedDate, "Not Completed", "Job_JobMetaWarranty_ExternalCompletedDate") - @AjaxHelpers.AjaxLoader() - - } - else - { - @CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalCompletedDate, "Unknown/None", null) - } -
Warranty Completed + + @if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ExternalCompletedDate)) + { + @CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalCompletedDate, "Not Completed", "Job_JobMetaWarranty_ExternalCompletedDate") + @AjaxHelpers.AjaxLoader() + + } + else + { + @CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalCompletedDate, "Unknown/None", null) + } +
Actions + + @if (Model.Job.CanLogWarranty()) + { + @Html.ActionLinkSmallButton("Log Warranty", MVC.Job.LogWarranty(Model.Job.Id, null, null), "Job_Show_Warranty_Actions_LogWarranty_Button") + } + else + { + <None> + } +
\r\n"); +" });\r\n \r\n"); - #line 26 "..\..\Views\Job\JobParts\Warranty.cshtml" - } - else - { - if (string.IsNullOrWhiteSpace(Model.Job.JobMetaWarranty.ExternalName)) + #line 28 "..\..\Views\Job\JobParts\Warranty.cshtml" + } + else { + if (string.IsNullOrWhiteSpace(Model.Job.JobMetaWarranty.ExternalName)) + { #line default #line hidden @@ -162,10 +178,10 @@ WriteLiteral(" class=\"smallMessage\""); WriteLiteral("><Unknown/None>"); - #line 30 "..\..\Views\Job\JobParts\Warranty.cshtml" - } - else - { + #line 32 "..\..\Views\Job\JobParts\Warranty.cshtml" + } + else + { #line default #line hidden @@ -176,8 +192,8 @@ WriteLiteral(" id=\"Job_JobMetaWarranty_ExternalName\""); WriteLiteral(">"); - #line 32 "..\..\Views\Job\JobParts\Warranty.cshtml" - Write(Model.Job.JobMetaWarranty.ExternalName); + #line 34 "..\..\Views\Job\JobParts\Warranty.cshtml" + Write(Model.Job.JobMetaWarranty.ExternalName); #line default @@ -185,70 +201,72 @@ WriteLiteral(">"); WriteLiteral(""); - #line 32 "..\..\Views\Job\JobParts\Warranty.cshtml" - } - } + #line 34 "..\..\Views\Job\JobParts\Warranty.cshtml" + } + } #line default #line hidden -WriteLiteral(" \r\n \r\n \r\n \r\n \r\n"); + +WriteLiteral(" \r\n Warranty Logged\r\n \r\n \r\n"); +WriteLiteral(">Warranty Logged\r\n \r\n \r\n"); - #line 40 "..\..\Views\Job\JobParts\Warranty.cshtml" - - - #line default - #line hidden - - #line 40 "..\..\Views\Job\JobParts\Warranty.cshtml" - if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ExternalLoggedDate)) - { + #line 42 "..\..\Views\Job\JobParts\Warranty.cshtml" #line default #line hidden #line 42 "..\..\Views\Job\JobParts\Warranty.cshtml" - Write(CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalLoggedDate, "Not Logged", "Job_JobMetaWarranty_ExternalLoggedDate")); + if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ExternalLoggedDate)) + { + + + #line default + #line hidden + + #line 44 "..\..\Views\Job\JobParts\Warranty.cshtml" + Write(CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalLoggedDate, "Not Logged", "Job_JobMetaWarranty_ExternalLoggedDate")); #line default #line hidden - #line 42 "..\..\Views\Job\JobParts\Warranty.cshtml" - - + #line 44 "..\..\Views\Job\JobParts\Warranty.cshtml" + + #line default #line hidden - #line 43 "..\..\Views\Job\JobParts\Warranty.cshtml" - Write(AjaxHelpers.AjaxLoader()); + #line 45 "..\..\Views\Job\JobParts\Warranty.cshtml" + Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 43 "..\..\Views\Job\JobParts\Warranty.cshtml" - + #line 45 "..\..\Views\Job\JobParts\Warranty.cshtml" + #line default #line hidden -WriteLiteral(" \r\n document.DiscoFunctions.DateDialogCreateUpdater(\'"); +WriteLiteral(">\r\n document.DiscoFunctions.DateDialogCreateUpdater(\'"); - #line 45 "..\..\Views\Job\JobParts\Warranty.cshtml" - Write(Url.Action(MVC.API.Job.Update(Model.Job.Id, null))); + #line 47 "..\..\Views\Job\JobParts\Warranty.cshtml" + Write(Url.Action(MVC.API.Job.Update(Model.Job.Id, null))); #line default @@ -257,128 +275,130 @@ WriteLiteral("\', \'Warranty Logged\', \'Job_JobMetaWarranty_ExternalLoggedDate\ "ternalLoggedDate\', \'Not Logged\', \'"); - #line 45 "..\..\Views\Job\JobParts\Warranty.cshtml" - Write(Model.Job.OpenedDate.ToISO8601()); - - - #line default - #line hidden -WriteLiteral("\', false);\r\n \r\n"); - - #line 47 "..\..\Views\Job\JobParts\Warranty.cshtml" - } - else - { - + Write(Model.Job.OpenedDate.ToISO8601()); + + + #line default + #line hidden +WriteLiteral("\', false);\r\n \r\n"); + + + #line 49 "..\..\Views\Job\JobParts\Warranty.cshtml" + } + else + { + #line default #line hidden - #line 50 "..\..\Views\Job\JobParts\Warranty.cshtml" - Write(CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalLoggedDate, "Unknown/None", null)); + #line 52 "..\..\Views\Job\JobParts\Warranty.cshtml" + Write(CommonHelpers.FriendlyDate(Model.Job.JobMetaWarranty.ExternalLoggedDate, "Unknown/None", null)); #line default #line hidden - #line 50 "..\..\Views\Job\JobParts\Warranty.cshtml" - - } + #line 52 "..\..\Views\Job\JobParts\Warranty.cshtml" + + } #line default #line hidden -WriteLiteral(" \r\n \r\n \r\n \r\n \r\n"); + +WriteLiteral(" \r\n Warranty Reference\r\n \r\n \r\n"); +WriteLiteral(">Warranty Reference\r\n \r\n \r\n"); - #line 58 "..\..\Views\Job\JobParts\Warranty.cshtml" - - - #line default - #line hidden - - #line 58 "..\..\Views\Job\JobParts\Warranty.cshtml" - if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ExternalReference)) - { + #line 60 "..\..\Views\Job\JobParts\Warranty.cshtml" #line default #line hidden #line 60 "..\..\Views\Job\JobParts\Warranty.cshtml" - Write(Html.EditorFor(m => m.Job.JobMetaWarranty.ExternalReference)); - - - #line default - #line hidden - - #line 60 "..\..\Views\Job\JobParts\Warranty.cshtml" - - - - #line default - #line hidden - - #line 61 "..\..\Views\Job\JobParts\Warranty.cshtml" - Write(AjaxHelpers.AjaxSave()); - - - #line default - #line hidden - - #line 61 "..\..\Views\Job\JobParts\Warranty.cshtml" - - + if (Authorization.Has(Claims.Job.Properties.WarrantyProperties.ExternalReference)) + { + #line default #line hidden #line 62 "..\..\Views\Job\JobParts\Warranty.cshtml" - Write(AjaxHelpers.AjaxLoader()); + Write(Html.EditorFor(m => m.Job.JobMetaWarranty.ExternalReference)); #line default #line hidden #line 62 "..\..\Views\Job\JobParts\Warranty.cshtml" - + + + + #line default + #line hidden + + #line 63 "..\..\Views\Job\JobParts\Warranty.cshtml" + Write(AjaxHelpers.AjaxSave()); #line default #line hidden -WriteLiteral("