11 Commits

Author SHA1 Message Date
Gary Sharp 09f9f2d427 version bump for v2.4 release 2024-09-26 16:33:55 +10:00
Gary Sharp 390857e065 attempt to preserve IIS bindings so future installations can restore them 2024-09-25 18:16:32 +10:00
Gary Sharp e0d620bf67 feature: lodge insurance 2024-09-25 16:21:51 +10:00
Gary Sharp 78b7b059ea feature: expression helpers - basic email sending 2024-05-16 22:11:10 +10:00
Gary Sharp bb846d14c5 feature: job preferences - On Device Ready For Return expression 2024-05-16 22:09:42 +10:00
Gary Sharp 565e1707ce fix: importing new devices fails for domain joined machines with assigned users 2024-04-08 18:11:03 +10:00
Gary Sharp a675e4a6e9 Feature: Provide CurrentDeviceUserAssignments for use by document expressions 2024-03-28 11:30:39 +11:00
Gary Sharp d8eb8fec83 global support license and validation 2024-01-26 16:23:26 +11:00
Gary Sharp f90eda4101 add pending enrollment identifier 2024-01-24 16:38:50 +11:00
Gary Sharp 37e2e5a08c feature: pending device enrollment approval 2024-01-21 14:06:11 +11:00
Gary Sharp 6af83cbdb2 Merge branch 'device-flags' 2024-01-14 19:13:51 +11:00
123 changed files with 8660 additions and 2435 deletions
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.3.23161.0650")] [assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.3.23161.0650")] [assembly: AssemblyFileVersion("2.4.24270.0000")]
@@ -41,6 +41,9 @@ namespace Disco.Client.Extensions
if (!string.IsNullOrEmpty(enrolResponse.ErrorMessage)) if (!string.IsNullOrEmpty(enrolResponse.ErrorMessage))
throw new ClientServiceException("Enrolment", enrolResponse.ErrorMessage); throw new ClientServiceException("Enrolment", enrolResponse.ErrorMessage);
if (enrolResponse.IsPending)
return;
// Offline Domain Join // Offline Domain Join
bool requireReboot = enrolResponse.ApplyOfflineDomainJoin(); bool requireReboot = enrolResponse.ApplyOfflineDomainJoin();
+30 -7
View File
@@ -122,17 +122,40 @@ namespace Disco.Client
EnrolResponse response = null; EnrolResponse response = null;
// Build Request // Build Request
Presentation.UpdateStatus("Enrolling Device", "Building enrolment request and preparing to send data to the server.", true, -1); Presentation.UpdateStatus("Enrolling Device", "Building enrollment request and preparing to send data to the server.", true, -1);
request = new Enrol(); request = new Enrol();
request.Build(); request.Build();
// Send Request var startTime = DateTimeOffset.Now;
Presentation.UpdateStatus("Enrolling Device", "Sending the enrolment request to the server.", true, -1); do
response = request.Post(Program.IsAuthenticated); {
// Send Request
Presentation.UpdateStatus("Enrolling Device", "Sending the enrollment request to the server.", true, -1);
response = request.Post(Program.IsAuthenticated);
// Process Response // Process Response
Presentation.UpdateStatus("Enrolling Device", "Processing the enrolment response from the server.", true, -1); Presentation.UpdateStatus("Enrolling Device", "Processing the enrollment response from the server.", true, -1);
response.Process(); response.Process();
if (response.IsPending)
{
request.PendingSessionId = response.SessionId;
request.PendingAuthorization = response.PendingAuthorization;
// Session Pending
var totalSeconds = (response.PendingTimeout - startTime).TotalSeconds;
var secondsConsumed = (DateTimeOffset.Now - startTime).TotalSeconds;
var progress = (int)((secondsConsumed / totalSeconds) * 100);
Presentation.UpdateStatus($"Pending Device Enrollment Approval: {response.PendingIdentifier}", $"Waiting for enrollment session '{response.PendingIdentifier}' to be approved.{Environment.NewLine}Reason: {response.PendingReason}", true, progress);
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));
}
else
{
// Session Complete
break;
}
} while (true);
// Complete // Complete
return true; return true;
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.3.23161.0650")] [assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.3.23161.0650")] [assembly: AssemblyFileVersion("2.4.24270.0000")]
+1 -1
View File
@@ -61,7 +61,7 @@ namespace Disco.ClientBootstrapper
this.progressBar.Visible = true; this.progressBar.Visible = true;
if (Progress.HasValue) if (Progress.HasValue)
{ {
if (Progress.Value > 0) if (Progress.Value >= 0)
{ {
this.progressBar.Value = Math.Min(Progress.Value, 100); this.progressBar.Value = Math.Min(Progress.Value, 100);
this.progressBar.Style = ProgressBarStyle.Continuous; this.progressBar.Style = ProgressBarStyle.Continuous;
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.3.23161.0650")] [assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.3.23161.0650")] [assembly: AssemblyFileVersion("2.4.24270.0000")]
@@ -1,4 +1,5 @@
using Disco.Data.Repository; using Disco.Data.Repository;
using System;
namespace Disco.Data.Configuration.Modules namespace Disco.Data.Configuration.Modules
{ {
@@ -6,33 +7,24 @@ namespace Disco.Data.Configuration.Modules
{ {
public BootstrapperConfiguration(DiscoDataContext Database) : base(Database) { } public BootstrapperConfiguration(DiscoDataContext Database) : base(Database) { }
public override string Scope public override string Scope { get; } = "Bootstrapper";
{
get { return "Bootstrapper"; }
}
public string MacSshUsername public string MacSshUsername
{ {
get get => Get("root");
{ set => Set(value);
return this.Get("root");
}
set
{
this.Set(value);
}
} }
public string MacSshPassword public string MacSshPassword
{ {
get get => GetDeobsfucated(string.Empty);
{ set => SetObsfucated(value);
return this.GetDeobsfucated(string.Empty); }
}
set public TimeSpan PendingTimeout
{ {
this.SetObsfucated(value); get => TimeSpan.FromSeconds(Get(30 * 60)); // 30 minutes default
} set => Set((int)value.TotalSeconds);
} }
} }
} }
@@ -75,6 +75,12 @@ namespace Disco.Data.Configuration.Modules
set { Set(value); } set { Set(value); }
} }
public string OnDeviceReadyForReturnExpression
{
get { return Get<string>(null); }
set { Set(value); }
}
public string OnCloseExpression public string OnCloseExpression
{ {
get { return Get<string>(null); } get { return Get<string>(null); }
+20 -25
View File
@@ -319,20 +319,27 @@ namespace Disco.Data.Configuration
#endregion #endregion
#region UpdateCheck #region UpdateCheck
public string DeploymentId public bool IsLicensed
{ {
get get => LicenseKey != null && LicenseExpiresOn != null && LicenseExpiresOn > DateTime.UtcNow && LicenseError == null;
{
return Get<string>(null);
}
} }
public string DeploymentSecret public string LicenseKey
{ {
get get => Get<string>(null);
{ set => Set(value);
return Get<string>(null);
}
} }
public DateTime? LicenseExpiresOn
{
get => Get<DateTime?>(null);
set => Set(value);
}
public string LicenseError
{
get => Get<string>(null);
set => Set(value);
}
public string DeploymentId => Get<string>(null);
public string DeploymentSecret => Get<string>(null);
public short DeploymentChecksum public short DeploymentChecksum
{ {
get get
@@ -351,22 +358,10 @@ namespace Disco.Data.Configuration
} }
public UpdateResponseV2 UpdateLastCheckResponse public UpdateResponseV2 UpdateLastCheckResponse
{ {
get get => Get<UpdateResponseV2>(null);
{ set => Set(value);
return Get<UpdateResponseV2>(null);
}
set
{
Set(value);
}
}
public bool UpdateBetaDeployment
{
get
{
return Get(false);
}
} }
public bool UpdateBetaDeployment => Get(false);
public Version InstalledDatabaseVersion public Version InstalledDatabaseVersion
{ {
get get
+7
View File
@@ -179,6 +179,10 @@
<Compile Include="Migrations\202401130531317_DBv23.Designer.cs"> <Compile Include="Migrations\202401130531317_DBv23.Designer.cs">
<DependentUpon>202401130531317_DBv23.cs</DependentUpon> <DependentUpon>202401130531317_DBv23.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Migrations\202403030134280_DBv24.cs" />
<Compile Include="Migrations\202403030134280_DBv24.Designer.cs">
<DependentUpon>202403030134280_DBv24.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\Configuration.cs" /> <Compile Include="Migrations\Configuration.cs" />
<Compile Include="Migrations\DiscoDataMigrator.cs" /> <Compile Include="Migrations\DiscoDataMigrator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
@@ -263,6 +267,9 @@
<EmbeddedResource Include="Migrations\202401130531317_DBv23.resx"> <EmbeddedResource Include="Migrations\202401130531317_DBv23.resx">
<DependentUpon>202401130531317_DBv23.cs</DependentUpon> <DependentUpon>202401130531317_DBv23.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Migrations\202403030134280_DBv24.resx">
<DependentUpon>202403030134280_DBv24.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+27
View File
@@ -0,0 +1,27 @@
// <auto-generated />
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
public sealed partial class DBv24 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv24));
string IMigrationMetadata.Id
{
get { return "202403030134280_DBv24"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,20 @@
namespace Disco.Data.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class DBv24 : DbMigration
{
public override void Up()
{
AddColumn("dbo.JobMetaInsurances", "Insurer", c => c.String(maxLength: 200));
AddColumn("dbo.JobMetaInsurances", "InsurerReference", c => c.String(maxLength: 200));
}
public override void Down()
{
DropColumn("dbo.JobMetaInsurances", "InsurerReference");
DropColumn("dbo.JobMetaInsurances", "Insurer");
}
}
}
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.3.23161.0650")] [assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.3.23161.0650")] [assembly: AssemblyFileVersion("2.4.24270.0000")]
+3
View File
@@ -25,5 +25,8 @@ namespace Disco.Models.ClientServices
public List<Certificate> Certificates { get; set; } public List<Certificate> Certificates { get; set; }
public List<WirelessProfile> WirelessProfiles { get; set; } public List<WirelessProfile> WirelessProfiles { get; set; }
public string PendingSessionId { get; set; }
public string PendingAuthorization { get; set; }
} }
} }
@@ -1,4 +1,5 @@
using Disco.Models.ClientServices.EnrolmentInformation; using Disco.Models.ClientServices.EnrolmentInformation;
using System;
namespace Disco.Models.ClientServices namespace Disco.Models.ClientServices
{ {
@@ -26,5 +27,11 @@ namespace Disco.Models.ClientServices
public bool RequireReboot { get; set; } public bool RequireReboot { get; set; }
public string ErrorMessage { get; set; } public string ErrorMessage { get; set; }
public bool IsPending { get; set; }
public string PendingAuthorization { get; set; }
public string PendingReason { get; set; }
public DateTimeOffset PendingTimeout { get; set; }
public string PendingIdentifier { get; set; }
} }
} }
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.3.23161.0650")] [assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.3.23161.0650")] [assembly: AssemblyFileVersion("2.4.24270.0000")]
+15
View File
@@ -53,6 +53,21 @@ namespace Disco.Models.Repository
public virtual IList<Job> Jobs { get; set; } public virtual IList<Job> Jobs { get; set; }
public virtual IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; } public virtual IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; }
/// <summary>
/// A list of the current device assignments, ordered by the most recent assignment date.
/// </summary>
[NotMapped]
public IList<DeviceUserAssignment> CurrentDeviceUserAssignments
{
get
{
return DeviceUserAssignments?
.Where(dua => dua.UnassignedDate is null)
.OrderByDescending(dua => dua.AssignedDate)
.ToList();
}
}
public override string ToString() public override string ToString()
{ {
if (DeviceModel != null) if (DeviceModel != null)
@@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
@@ -58,6 +55,10 @@ namespace Disco.Models.Repository
[DisplayFormat(ApplyFormatInEditMode = true, ConvertEmptyStringToNull = true, DataFormatString = "{0:yyyy/MM/dd hh:mm tt}", HtmlEncode = false)] [DisplayFormat(ApplyFormatInEditMode = true, ConvertEmptyStringToNull = true, DataFormatString = "{0:yyyy/MM/dd hh:mm tt}", HtmlEncode = false)]
public DateTime? ClaimFormSentDate { get; set; } public DateTime? ClaimFormSentDate { get; set; }
public string ClaimFormSentUserId { get; set; } public string ClaimFormSentUserId { get; set; }
[StringLength(200)]
public string Insurer { get; set; }
[StringLength(200)]
public string InsurerReference { get; set; }
[Required, ForeignKey("JobId")] [Required, ForeignKey("JobId")]
public virtual Job Job { get; set; } public virtual Job Job { get; set; }
+1 -1
View File
@@ -25,7 +25,7 @@ namespace Disco.Models.Services.Messaging
public Email(string to, string subject, string body) public Email(string to, string subject, string body)
: this() : this()
{ {
To.Add(to); To.AddRange(ParseEmailAddresses(to));
Subject = subject; Subject = subject;
Body = body; Body = body;
} }
@@ -4,5 +4,6 @@
{ {
public string Name { get; set; } public string Name { get; set; }
public byte[] Data { get; set; } public byte[] Data { get; set; }
public string MediaType { get; set; }
} }
} }
@@ -19,6 +19,10 @@ namespace Disco.Models.Services.Users.Contact
User = user; User = user;
ContactType = contactType; ContactType = contactType;
Source = source; Source = source;
if (name != null && name.IndexOf(',') >= 0)
name = name.Replace(',', ' ');
Name = name; Name = name;
} }
@@ -1,13 +1,8 @@
using System; namespace Disco.Models.UI.Config.Enrolment
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.UI.Config.Enrolment
{ {
public interface ConfigEnrolmentIndexModel : BaseUIModel public interface ConfigEnrolmentIndexModel : BaseUIModel
{ {
string MacSshUsername { get; set; } string MacSshUsername { get; set; }
int PendingTimeoutMinutes { get; set; }
} }
} }
+4 -1
View File
@@ -1,4 +1,6 @@
using Disco.Models.Services.Jobs.JobLists; using Disco.Models.ClientServices;
using Disco.Models.Services.Jobs.JobLists;
using System.Collections.Generic;
namespace Disco.Models.UI.Job namespace Disco.Models.UI.Job
{ {
@@ -6,5 +8,6 @@ namespace Disco.Models.UI.Job
{ {
JobTableModel MyJobs { get; set; } JobTableModel MyJobs { get; set; }
JobTableModel StaleJobs { get; set; } JobTableModel StaleJobs { get; set; }
List<EnrolResponse> PendingEnrollments { get; set; }
} }
} }
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.3.23161.0650")] [assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.3.23161.0650")] [assembly: AssemblyFileVersion("2.4.24270.0000")]
+10 -2
View File
@@ -109,6 +109,7 @@ namespace Disco.Services.Authorization
{ "Job.Actions.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.Delete, (c, v) => c.Job.Actions.Delete = v, "Delete Jobs", "Can delete jobs", false) }, { "Job.Actions.Delete", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.Delete, (c, v) => c.Job.Actions.Delete = v, "Delete Jobs", "Can delete jobs", false) },
{ "Job.Actions.ForceClose", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.ForceClose, (c, v) => c.Job.Actions.ForceClose = v, "Force Close Jobs", "Can force close jobs", false) }, { "Job.Actions.ForceClose", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.ForceClose, (c, v) => c.Job.Actions.ForceClose = v, "Force Close Jobs", "Can force close jobs", false) },
{ "Job.Actions.GenerateDocuments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.GenerateDocuments, (c, v) => c.Job.Actions.GenerateDocuments = v, "Generate Documents", "Can generate documents for jobs", false) }, { "Job.Actions.GenerateDocuments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.GenerateDocuments, (c, v) => c.Job.Actions.GenerateDocuments = v, "Generate Documents", "Can generate documents for jobs", false) },
{ "Job.Actions.LogInsurance", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.LogInsurance, (c, v) => c.Job.Actions.LogInsurance = v, "Log Insurance", "Can log insurance for non-warranty jobs", false) },
{ "Job.Actions.LogRepair", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.LogRepair, (c, v) => c.Job.Actions.LogRepair = v, "Log Repair", "Can log repair for non-warranty jobs", false) }, { "Job.Actions.LogRepair", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.LogRepair, (c, v) => c.Job.Actions.LogRepair = v, "Log Repair", "Can log repair for non-warranty jobs", false) },
{ "Job.Actions.LogWarranty", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.LogWarranty, (c, v) => c.Job.Actions.LogWarranty = v, "Log Warranty", "Can log warranty for jobs", false) }, { "Job.Actions.LogWarranty", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.LogWarranty, (c, v) => c.Job.Actions.LogWarranty = v, "Log Warranty", "Can log warranty for jobs", false) },
{ "Job.Actions.RemoveAnyAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.RemoveAnyAttachments, (c, v) => c.Job.Actions.RemoveAnyAttachments = v, "Remove Any Attachments", "Can remove any attachments from jobs", false) }, { "Job.Actions.RemoveAnyAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Actions.RemoveAnyAttachments, (c, v) => c.Job.Actions.RemoveAnyAttachments = v, "Remove Any Attachments", "Can remove any attachments from jobs", false) },
@@ -133,7 +134,7 @@ namespace Disco.Services.Authorization
{ "Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent, (c, v) => c.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent = v, "Insurance Claim Form Sent Property", "Can update property", false) }, { "Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent, (c, v) => c.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent = v, "Insurance Claim Form Sent Property", "Can update property", false) },
{ "Job.Properties.NonWarrantyProperties.InsuranceDetails", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.InsuranceDetails, (c, v) => c.Job.Properties.NonWarrantyProperties.InsuranceDetails = v, "Insurance Detail Properties", "Can update insurance detail properties", false) }, { "Job.Properties.NonWarrantyProperties.InsuranceDetails", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.InsuranceDetails, (c, v) => c.Job.Properties.NonWarrantyProperties.InsuranceDetails = v, "Insurance Detail Properties", "Can update insurance detail properties", false) },
{ "Job.Properties.NonWarrantyProperties.InvoiceReceived", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.InvoiceReceived, (c, v) => c.Job.Properties.NonWarrantyProperties.InvoiceReceived = v, "Invoice Received Property", "Can update property", false) }, { "Job.Properties.NonWarrantyProperties.InvoiceReceived", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.InvoiceReceived, (c, v) => c.Job.Properties.NonWarrantyProperties.InvoiceReceived = v, "Invoice Received Property", "Can update property", false) },
{ "Job.Properties.NonWarrantyProperties.IsInsuranceClaim", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.IsInsuranceClaim, (c, v) => c.Job.Properties.NonWarrantyProperties.IsInsuranceClaim = v, "Is Insurance Claim Property", "Can update property", false) }, { "Job.Properties.NonWarrantyProperties.IsInsuranceClaim", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.IsInsuranceClaim, (c, v) => c.Job.Properties.NonWarrantyProperties.IsInsuranceClaim = v, "Is Insurance Claim Property", "Can update property", false) },
{ "Job.Properties.NonWarrantyProperties.PurchaseOrderRaised", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, 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.PurchaseOrderRaised", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, 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<Func<RoleClaims, bool>, Action<RoleClaims, bool>, 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.PurchaseOrderReference", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, 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<Func<RoleClaims, bool>, Action<RoleClaims, bool>, 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.PurchaseOrderSent", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, 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) },
@@ -337,6 +338,7 @@ namespace Disco.Services.Authorization
new ClaimNavigatorItem("Job.Actions.Delete", false), new ClaimNavigatorItem("Job.Actions.Delete", false),
new ClaimNavigatorItem("Job.Actions.ForceClose", false), new ClaimNavigatorItem("Job.Actions.ForceClose", false),
new ClaimNavigatorItem("Job.Actions.GenerateDocuments", false), new ClaimNavigatorItem("Job.Actions.GenerateDocuments", false),
new ClaimNavigatorItem("Job.Actions.LogInsurance", false),
new ClaimNavigatorItem("Job.Actions.LogRepair", false), new ClaimNavigatorItem("Job.Actions.LogRepair", false),
new ClaimNavigatorItem("Job.Actions.LogWarranty", false), new ClaimNavigatorItem("Job.Actions.LogWarranty", false),
new ClaimNavigatorItem("Job.Actions.RemoveAnyAttachments", false), new ClaimNavigatorItem("Job.Actions.RemoveAnyAttachments", false),
@@ -647,6 +649,7 @@ namespace Disco.Services.Authorization
c.Job.Actions.Delete = true; c.Job.Actions.Delete = true;
c.Job.Actions.ForceClose = true; c.Job.Actions.ForceClose = true;
c.Job.Actions.GenerateDocuments = true; c.Job.Actions.GenerateDocuments = true;
c.Job.Actions.LogInsurance = true;
c.Job.Actions.LogRepair = true; c.Job.Actions.LogRepair = true;
c.Job.Actions.LogWarranty = true; c.Job.Actions.LogWarranty = true;
c.Job.Actions.RemoveAnyAttachments = true; c.Job.Actions.RemoveAnyAttachments = true;
@@ -1341,6 +1344,11 @@ namespace Disco.Services.Authorization
/// </summary> /// </summary>
public const string GenerateDocuments = "Job.Actions.GenerateDocuments"; public const string GenerateDocuments = "Job.Actions.GenerateDocuments";
/// <summary>Log Insurance
/// <para>Can log insurance for non-warranty jobs</para>
/// </summary>
public const string LogInsurance = "Job.Actions.LogInsurance";
/// <summary>Log Repair /// <summary>Log Repair
/// <para>Can log repair for non-warranty jobs</para> /// <para>Can log repair for non-warranty jobs</para>
/// </summary> /// </summary>
@@ -1481,7 +1489,7 @@ namespace Disco.Services.Authorization
/// </summary> /// </summary>
public const string InvoiceReceived = "Job.Properties.NonWarrantyProperties.InvoiceReceived"; public const string InvoiceReceived = "Job.Properties.NonWarrantyProperties.InvoiceReceived";
/// <summary>Is Insurance Claim Property /// <summary>Is Insurance Claim Property
/// <para>Can update property</para> /// <para>Can update property</para>
/// </summary> /// </summary>
public const string IsInsuranceClaim = "Job.Properties.NonWarrantyProperties.IsInsuranceClaim"; public const string IsInsuranceClaim = "Job.Properties.NonWarrantyProperties.IsInsuranceClaim";
@@ -23,10 +23,12 @@
[ClaimDetails("Remove from Any Queues", "Can remove from any job queues")] [ClaimDetails("Remove from Any Queues", "Can remove from any job queues")]
public bool RemoveAnyQueues { get; set; } public bool RemoveAnyQueues { get; set; }
[ClaimDetails("Log Warranty", "Can log warranty for jobs")] [ClaimDetails("Lodge Warranty", "Can lodge warranty for jobs")]
public bool LogWarranty { get; set; } public bool LogWarranty { get; set; }
[ClaimDetails("Log Repair", "Can log repair for non-warranty jobs")] [ClaimDetails("Lodge Repair", "Can lodge repair for non-warranty jobs")]
public bool LogRepair { get; set; } public bool LogRepair { get; set; }
[ClaimDetails("Lodge Insurance", "Can lodge insurance for non-warranty jobs")]
public bool LogInsurance { get; set; }
[ClaimDetails("Convert HWar Jobs To HNWar", "Can convert warranty jobs to non-warranty jobs")] [ClaimDetails("Convert HWar Jobs To HNWar", "Can convert warranty jobs to non-warranty jobs")]
public bool ConvertHWarToHNWar { get; set; } public bool ConvertHWarToHNWar { get; set; }
@@ -8,7 +8,7 @@
[ClaimDetails("Edit Components", "Can edit and remove job components")] [ClaimDetails("Edit Components", "Can edit and remove job components")]
public bool EditComponents { get; set; } public bool EditComponents { get; set; }
[ClaimDetails("Is Insurance Claim Property", "Can update property")] [ClaimDetails("Is Insurance Claim Property", "Can update property")]
public bool IsInsuranceClaim { get; set; } public bool IsInsuranceClaim { get; set; }
[ClaimDetails("Insurance Claim Form Sent Property", "Can update property")] [ClaimDetails("Insurance Claim Form Sent Property", "Can update property")]
@@ -14,6 +14,10 @@ namespace Disco.Services.Devices.Enrolment
SessionProgress, SessionProgress,
SessionDevice, SessionDevice,
SessionDeviceInfo, SessionDeviceInfo,
SessionPending,
SessionPendingApproved,
SessionPendingRejected,
SessionContinuing,
SessionFinished = 20, SessionFinished = 20,
SessionDiagnosticInformation, SessionDiagnosticInformation,
SessionWarning, SessionWarning,
@@ -43,7 +47,7 @@ namespace Disco.Services.Devices.Enrolment
{ {
get get
{ {
return "Device Enrolment"; return "Device Enrollment";
} }
} }
public override int ModuleId public override int ModuleId
@@ -77,6 +81,44 @@ namespace Disco.Services.Devices.Enrolment
System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType) System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType)
}); });
} }
public static void LogSessionPending(string SessionId, string HostId, EnrolmentTypes EnrolmentType, string Reason, string Identifier)
{
Log(EventTypeIds.SessionPending, new object[]
{
SessionId,
HostId,
System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType),
Reason,
Identifier
});
}
public static void LogSessionPendingApproved(string SessionId, string Username, string Reason)
{
Log(EventTypeIds.SessionPendingApproved, new object[]
{
SessionId,
Username,
Reason
});
}
public static void LogSessionPendingRejected(string SessionId, string Username, string Reason)
{
Log(EventTypeIds.SessionPendingRejected, new object[]
{
SessionId,
Username,
Reason
});
}
public static void LogSessionContinuing(string SessionId, string HostId, EnrolmentTypes EnrolmentType)
{
Log(EventTypeIds.SessionContinuing, new object[]
{
SessionId,
HostId,
System.Enum.GetName(EnrolmentType.GetType(), EnrolmentType)
});
}
public static void LogSessionDevice(string SessionId, string DeviceSerialNumber, int? DeviceModelId) public static void LogSessionDevice(string SessionId, string DeviceSerialNumber, int? DeviceModelId)
{ {
Log(EventTypeIds.SessionDevice, new object[] Log(EventTypeIds.SessionDevice, new object[]
@@ -298,7 +340,7 @@ namespace Disco.Services.Devices.Enrolment
Id = (int)EventTypeIds.SessionStarting, Id = (int)EventTypeIds.SessionStarting,
ModuleId = _ModuleId, ModuleId = _ModuleId,
Name = "Session Starting", Name = "Session Starting",
Format = "Starting '{2}' Enrolment for {1} (Session# {0})", Format = "Starting '{2}' Enrollment for {1} (Session# {0})",
Severity = 0, Severity = 0,
UseLive = true, UseLive = true,
UsePersist = true, UsePersist = true,
@@ -338,6 +380,50 @@ namespace Disco.Services.Devices.Enrolment
UseDisplay = true UseDisplay = true
}, },
new LogEventType new LogEventType
{
Id = (int)EventTypeIds.SessionPending,
ModuleId = _ModuleId,
Name = "Session Pending",
Format = "Pending '{2}' Enrollment for {1} (Session# {0}; Reason: {3}; Identifier: {4})",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.SessionPendingApproved,
ModuleId = _ModuleId,
Name = "Session Pending Approved",
Format = "Pending enrollment approved by {1} (Session# {0}; Reason: {2})",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.SessionPendingRejected,
ModuleId = _ModuleId,
Name = "Session Pending Rejected",
Format = "Pending enrollment rejected by {1} (Session# {0}; Reason: {2})",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.SessionContinuing,
ModuleId = _ModuleId,
Name = "Session Continuing",
Format = "Continuing '{2}' Enrollment for {1} (Session# {0})",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{ {
Id = (int)EventTypeIds.SessionFinished, Id = (int)EventTypeIds.SessionFinished,
ModuleId = _ModuleId, ModuleId = _ModuleId,
@@ -5,15 +5,88 @@ using Disco.Services.Authorization;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Users; using Disco.Services.Users;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Cryptography;
namespace Disco.Services.Devices.Enrolment namespace Disco.Services.Devices.Enrolment
{ {
public static class WindowsDeviceEnrolment public static class WindowsDeviceEnrolment
{ {
private static readonly string pendingIdentifierAlphabet = "23456789ABCDEFGHJKMNPQRSTWXYZ";
private static readonly Random pendingIdentifierRng = new Random();
private static readonly ConcurrentDictionary<string, EnrolResponse> pendingEnrolments = new ConcurrentDictionary<string, EnrolResponse>();
private static void CleanupPendingEnrolments()
{
var now = DateTimeOffset.Now;
var expiredEnrolments = pendingEnrolments
.Where(e => e.Value.PendingTimeout < now)
.Select(kvp => kvp.Key).ToList();
foreach (var expiredEnrolment in expiredEnrolments)
pendingEnrolments.TryRemove(expiredEnrolment, out _);
}
private static string GeneratePendingIdentifier()
{
var identifier = default(string);
var chars = new char[4];
var retryAllowed = 100;
while (--retryAllowed > 0)
{
lock (pendingIdentifierRng)
{
for (var i = 0; i < chars.Length; i++)
{
chars[i] = pendingIdentifierAlphabet[pendingIdentifierRng.Next(pendingIdentifierAlphabet.Length)];
}
}
identifier = new string(chars);
if (!GetPendingEnrolments().Any(e => string.Equals(e.PendingIdentifier, identifier, StringComparison.Ordinal)))
break;
}
return identifier;
}
public static List<EnrolResponse> GetPendingEnrolments()
{
var now = DateTimeOffset.Now;
return pendingEnrolments.Values
.Where(e => e.PendingTimeout > now && e.IsPending)
.ToList();
}
public static void ResolvePendingEnrollment(string sessionId, bool approve, string username, string reason)
{
if (!pendingEnrolments.TryGetValue(sessionId, out var enrolResponse))
throw new InvalidOperationException("The pending session is invalid or has expired");
if (enrolResponse.PendingTimeout < DateTimeOffset.Now)
{
pendingEnrolments.TryRemove(sessionId, out _);
throw new InvalidOperationException("The pending session has expired");
}
if (!enrolResponse.IsPending)
return;
enrolResponse.IsPending = false;
if (approve)
{
enrolResponse.ErrorMessage = null;
EnrolmentLog.LogSessionPendingApproved(sessionId, username, reason);
}
else
{
enrolResponse.ErrorMessage = $"Enrollment rejected";
EnrolmentLog.LogSessionPendingRejected(sessionId, username, reason);
}
}
public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Enrol Request) public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Enrol Request)
{ {
CleanupPendingEnrolments();
ADMachineAccount adMachineAccount = null; ADMachineAccount adMachineAccount = null;
EnrolResponse response = new EnrolResponse(); EnrolResponse response = new EnrolResponse();
@@ -29,14 +102,49 @@ namespace Disco.Services.Devices.Enrolment
return domain.GetAvailableDomainController(RequireWritable: true); return domain.GetAvailableDomainController(RequireWritable: true);
}); });
string sessionId = Guid.NewGuid().ToString("B");
response.SessionId = sessionId;
EnrolmentLog.LogSessionStarting(sessionId, Request.SerialNumber, EnrolmentTypes.Normal);
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
try try
{ {
string sessionId;
bool sessionApproved = false;
if (!string.IsNullOrWhiteSpace(Request.PendingSessionId))
{
if (!pendingEnrolments.TryGetValue(Request.PendingSessionId, out var pendingResponse))
throw new EnrolmentSafeException("The pending session is invalid or has expired");
if (pendingResponse.PendingTimeout < DateTimeOffset.Now)
{
pendingEnrolments.TryRemove(Request.PendingSessionId, out _);
throw new EnrolmentSafeException("The pending session has expired");
}
if (!string.Equals(pendingResponse.PendingAuthorization, Request.PendingAuthorization, StringComparison.Ordinal))
throw new EnrolmentSafeException("The pending session authorization is incorrect");
sessionId = pendingResponse.SessionId;
response = pendingResponse;
// still pending?
if (response.IsPending)
return response;
// session rejected?
if (!string.IsNullOrWhiteSpace(response.ErrorMessage))
throw new EnrolmentSafeException(response.ErrorMessage);
// session approved; continue
sessionApproved = true;
EnrolmentLog.LogSessionContinuing(sessionId, Request.SerialNumber, EnrolmentTypes.Normal);
}
else
{
sessionId = Guid.NewGuid().ToString("B");
response.SessionId = sessionId;
EnrolmentLog.LogSessionStarting(sessionId, Request.SerialNumber, EnrolmentTypes.Normal);
}
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
if (Request.SerialNumber.Contains("/") || Request.SerialNumber.Contains(@"\")) if (Request.SerialNumber.Contains("/") || Request.SerialNumber.Contains(@"\"))
throw new EnrolmentSafeException(@"The serial number cannot contain '/' or '\' characters."); throw new EnrolmentSafeException(@"The serial number cannot contain '/' or '\' characters.");
@@ -50,46 +158,72 @@ namespace Disco.Services.Devices.Enrolment
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.SerialNumber).FirstOrDefault(); Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.SerialNumber).FirstOrDefault();
EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco ICT Permissions"); EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco ICT Permissions");
if (isAuthenticated) if (!sessionApproved)
{ {
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices)) try
{ {
if (!authenticatedToken.Has(Claims.ComputerAccount)) if (isAuthenticated)
throw new EnrolmentSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.SerialNumber, authenticatedToken.User.UserId));
if (domain == null)
domain = ActiveDirectory.Context.GetDomainByName(Request.DNSDomainName);
if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.ComputerName), StringComparison.OrdinalIgnoreCase))
throw new EnrolmentSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.SerialNumber, authenticatedToken.User.UserId));
}
}
else
{
if (RepoDevice == null)
{
throw new EnrolmentSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.SerialNumber));
}
if (!RepoDevice.AllowUnauthenticatedEnrol)
{
if (RepoDevice.DeviceProfile.AllowUntrustedReimageJobEnrolment)
{ {
if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0) if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
{ {
throw new EnrolmentSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.SerialNumber)); if (!authenticatedToken.Has(Claims.ComputerAccount))
throw new EnrolmentSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.SerialNumber, authenticatedToken.User.UserId));
if (domain == null)
domain = ActiveDirectory.Context.GetDomainByName(Request.DNSDomainName);
if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.ComputerName), StringComparison.OrdinalIgnoreCase))
throw new EnrolmentSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.SerialNumber, authenticatedToken.User.UserId));
} }
} }
else else
{ {
throw new EnrolmentSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.SerialNumber)); if (RepoDevice == null)
{
throw new EnrolmentSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.SerialNumber));
}
if (!RepoDevice.AllowUnauthenticatedEnrol)
{
if (RepoDevice.DeviceProfile.AllowUntrustedReimageJobEnrolment)
{
if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0)
{
throw new EnrolmentSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.SerialNumber));
}
}
else
{
throw new EnrolmentSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.SerialNumber));
}
}
} }
} }
catch (EnrolmentSafeException ex)
{
response.IsPending = true;
response.PendingReason = ex.Message;
using (var rng = new RNGCryptoServiceProvider())
{
var authBytes = new byte[33]; // 264 bits (base64-aligned)
rng.GetBytes(authBytes);
response.PendingAuthorization = Convert.ToBase64String(authBytes);
}
response.PendingTimeout = DateTimeOffset.Now.Add(Database.DiscoConfiguration.Bootstrapper.PendingTimeout);
response.PendingIdentifier = GeneratePendingIdentifier();
EnrolmentLog.LogSessionPending(sessionId, Request.SerialNumber, EnrolmentTypes.Normal, response.PendingReason, response.PendingIdentifier);
if (pendingEnrolments.TryAdd(sessionId, response))
return response;
throw;
}
} }
if (Request.IsPartOfDomain && !string.IsNullOrWhiteSpace(Request.ComputerName)) if (Request.IsPartOfDomain && !string.IsNullOrWhiteSpace(Request.ComputerName))
{ {
EnrolmentLog.LogSessionProgress(sessionId, 20, "Loading Active Directory Computer Account"); EnrolmentLog.LogSessionProgress(sessionId, 20, "Loading Active Directory Computer Account");
System.Guid? uuidGuid = null; Guid? uuidGuid = null;
System.Guid? macAddressGuid = null; Guid? macAddressGuid = null;
if (!string.IsNullOrEmpty(Request.Hardware.UUID)) if (!string.IsNullOrEmpty(Request.Hardware.UUID))
uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.Hardware.UUID); uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.Hardware.UUID);
@@ -382,24 +516,26 @@ namespace Disco.Services.Devices.Enrolment
} }
catch (EnrolmentSafeException ex) catch (EnrolmentSafeException ex)
{ {
EnrolmentLog.LogSessionError(sessionId, ex); EnrolmentLog.LogSessionError(response.SessionId, ex);
return new EnrolResponse return new EnrolResponse
{ {
SessionId = sessionId, SessionId = response.SessionId,
ErrorMessage = ex.Message ErrorMessage = ex.Message
}; };
} }
catch (Exception ex2) catch (Exception ex2)
{ {
EnrolmentLog.LogSessionError(sessionId, ex2); EnrolmentLog.LogSessionError(response.SessionId, ex2);
throw ex2; throw ex2;
} }
finally finally
{ {
EnrolmentLog.LogSessionFinished(sessionId); if (!response.IsPending)
EnrolmentLog.LogSessionFinished(response.SessionId);
} }
return response; return response;
} }
} }
} }
@@ -119,16 +119,23 @@ namespace Disco.Services.Devices.Importing.Fields
// Add Assignment // Add Assignment
if (parsedValue != null) if (parsedValue != null)
{ {
var user = Database.Users.FirstOrDefault(u => u.UserId == parsedValue);
var assignment = new DeviceUserAssignment() var assignment = new DeviceUserAssignment()
{ {
Device = Device, Device = Device,
DeviceSerialNumber = Device.SerialNumber, DeviceSerialNumber = Device.SerialNumber,
AssignedUserId = parsedValue, AssignedUserId = user.UserId,
AssignedUser = user,
AssignedDate = DateTime.Now AssignedDate = DateTime.Now
}; };
Database.DeviceUserAssignments.Add(assignment); Database.DeviceUserAssignments.Add(assignment);
Device.AssignedUser = user;
Device.AssignedUserId = user.UserId;
}
else
{
Device.AssignedUserId = null;
} }
Device.AssignedUserId = parsedValue;
return true; return true;
} }
+13
View File
@@ -62,6 +62,11 @@
<Reference Include="Microsoft.Owin.Security, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Owin.Security, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.Security.4.2.2\lib\net45\Microsoft.Owin.Security.dll</HintPath> <HintPath>..\packages\Microsoft.Owin.Security.4.2.2\lib\net45\Microsoft.Owin.Security.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Web.Administration, Version=7.9.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\Installer\Microsoft.Web.Administration.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private> <Private>True</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath> <HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
@@ -324,6 +329,7 @@
<Compile Include="Expressions\ExpressionTypeMemberDescriptor.cs" /> <Compile Include="Expressions\ExpressionTypeMemberDescriptor.cs" />
<Compile Include="Expressions\Extensions\DataExt.cs" /> <Compile Include="Expressions\Extensions\DataExt.cs" />
<Compile Include="Expressions\Extensions\DeviceExt.cs" /> <Compile Include="Expressions\Extensions\DeviceExt.cs" />
<Compile Include="Expressions\Extensions\EmailExt.cs" />
<Compile Include="Expressions\Extensions\ImageExt.cs" /> <Compile Include="Expressions\Extensions\ImageExt.cs" />
<Compile Include="Expressions\Extensions\ImageResultImplementations\BaseImageExpressionResult.cs" /> <Compile Include="Expressions\Extensions\ImageResultImplementations\BaseImageExpressionResult.cs" />
<Compile Include="Expressions\Extensions\ImageResultImplementations\BitmapImageExpressionResult.cs" /> <Compile Include="Expressions\Extensions\ImageResultImplementations\BitmapImageExpressionResult.cs" />
@@ -367,8 +373,10 @@
<Compile Include="Interop\ActiveDirectory\IADObject.cs" /> <Compile Include="Interop\ActiveDirectory\IADObject.cs" />
<Compile Include="Interop\DiscoServices\DiscoServiceHelpers.cs" /> <Compile Include="Interop\DiscoServices\DiscoServiceHelpers.cs" />
<Compile Include="Interop\DiscoServices\Jobs.cs" /> <Compile Include="Interop\DiscoServices\Jobs.cs" />
<Compile Include="Interop\DiscoServices\LicenseValidationTask.cs" />
<Compile Include="Interop\DiscoServices\PluginLibrary.cs" /> <Compile Include="Interop\DiscoServices\PluginLibrary.cs" />
<Compile Include="Interop\DiscoServices\PluginLibraryUpdateTask.cs" /> <Compile Include="Interop\DiscoServices\PluginLibraryUpdateTask.cs" />
<Compile Include="Interop\IIS\PreserveIisBindingsTask.cs" />
<Compile Include="Interop\MimeTypes.cs" /> <Compile Include="Interop\MimeTypes.cs" />
<Compile Include="Interop\VicEduDept\VicSmart.cs" /> <Compile Include="Interop\VicEduDept\VicSmart.cs" />
<Compile Include="Interop\DiscoServices\UpdateQuery.cs" /> <Compile Include="Interop\DiscoServices\UpdateQuery.cs" />
@@ -411,6 +419,10 @@
<Compile Include="Plugins\Features\DetailsProvider\DetailsProviderService.cs" /> <Compile Include="Plugins\Features\DetailsProvider\DetailsProviderService.cs" />
<Compile Include="Plugins\Features\DetailsProvider\UserContactFeature.cs" /> <Compile Include="Plugins\Features\DetailsProvider\UserContactFeature.cs" />
<Compile Include="Plugins\Features\DocumentHandlerProvider\DocumentHandlerProviderFeature.cs" /> <Compile Include="Plugins\Features\DocumentHandlerProvider\DocumentHandlerProviderFeature.cs" />
<Compile Include="Plugins\Features\InsuranceProvider\InsuranceProviderFeature.cs" />
<Compile Include="Plugins\Features\InsuranceProvider\InsuranceProviderSubmitJobException.cs" />
<Compile Include="Plugins\Features\RepairProvider\RepairProvider2Feature.cs" />
<Compile Include="Plugins\Features\WarrantyProvider\WarrantyProvider2Feature.cs" />
<Compile Include="Plugins\Features\WirelessProfileProvider\ProvisionWirelessProfilesResult.cs" /> <Compile Include="Plugins\Features\WirelessProfileProvider\ProvisionWirelessProfilesResult.cs" />
<Compile Include="Plugins\Features\WirelessProfileProvider\WirelessProfile.cs" /> <Compile Include="Plugins\Features\WirelessProfileProvider\WirelessProfile.cs" />
<Compile Include="Plugins\Features\WirelessProfileProvider\WirelessProfileTransformation.cs" /> <Compile Include="Plugins\Features\WirelessProfileProvider\WirelessProfileTransformation.cs" />
@@ -539,6 +551,7 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PostBuildEvent> <PostBuildEvent>
+7 -1
View File
@@ -38,9 +38,10 @@ namespace Disco.Services.Expressions
public static void InitializeExpressions() public static void InitializeExpressions()
{ {
TypeRegistry.RegisterType("DataExt", typeof(Extensions.DataExt)); TypeRegistry.RegisterType("DataExt", typeof(Extensions.DataExt));
TypeRegistry.RegisterType("UserExt", typeof(Extensions.UserExt));
TypeRegistry.RegisterType("DeviceExt", typeof(Extensions.DeviceExt)); TypeRegistry.RegisterType("DeviceExt", typeof(Extensions.DeviceExt));
TypeRegistry.RegisterType("EmailExt", typeof(Extensions.EmailExt));
TypeRegistry.RegisterType("ImageExt", typeof(Extensions.ImageExt)); TypeRegistry.RegisterType("ImageExt", typeof(Extensions.ImageExt));
TypeRegistry.RegisterType("UserExt", typeof(Extensions.UserExt));
} }
public T EvaluateFirst<T>(object ExpressionContext, IDictionary Variables) public T EvaluateFirst<T>(object ExpressionContext, IDictionary Variables)
@@ -297,6 +298,11 @@ namespace Disco.Services.Expressions
typeof(Extensions.DeviceExt).AssemblyQualifiedName typeof(Extensions.DeviceExt).AssemblyQualifiedName
}, },
{
"EmailExt",
typeof(Extensions.EmailExt).AssemblyQualifiedName
},
{ {
"ImageExt", "ImageExt",
typeof(Extensions.ImageExt).AssemblyQualifiedName typeof(Extensions.ImageExt).AssemblyQualifiedName
@@ -0,0 +1,32 @@
using Disco.Models.Repository;
using Disco.Models.Services.Messaging;
using Disco.Services.Messaging;
using System;
namespace Disco.Services.Expressions.Extensions
{
public static class EmailExt
{
public static void SendToUser(User user, string subject, string body)
{
var to = user.EmailAddress;
if (string.IsNullOrWhiteSpace(to))
throw new Exception($"User ({user.UserId}) does not have an email address");
Send(to, subject, body);
}
public static void Send(string to, string subject, string body)
{
var email = new Email()
{
Subject = subject,
Body = body,
};
email.To.Add(to);
EmailService.SendEmail(email);
}
}
}
@@ -0,0 +1,167 @@
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Newtonsoft.Json;
using Quartz;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
namespace Disco.Services.Interop.DiscoServices
{
public class LicenseValidationTask : ScheduledTask
{
private const string jobMapLicenseKey = "License";
public override string TaskName { get { return "License Validation"; } }
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
if (Database.DiscoConfiguration.LicenseKey != null)
{
// Trigger in 1 + 0-29 minutes
var rng = new Random();
var delay = rng.Next(30) + 1;
TriggerBuilder triggerBuilder = TriggerBuilder.Create()
.StartAt(DateTimeOffset.Now.AddMinutes(delay));
ScheduleTask(triggerBuilder);
base.InitalizeScheduledTask(Database);
}
}
public static ScheduledTaskStatus ScheduleNow(string license)
{
var taskStatus = RunningStatus;
if (taskStatus != null)
return taskStatus;
else
{
var task = new LicenseValidationTask();
var taskData = new JobDataMap() { { jobMapLicenseKey, license } };
return task.ScheduleTask(taskData);
}
}
public static ScheduledTaskStatus RunningStatus =>
ScheduledTasks.GetTaskStatuses(typeof(LicenseValidationTask)).Where(ts => ts.IsRunning).FirstOrDefault();
protected override void ExecuteTask()
{
var license = ExecutionContext.JobDetail.JobDataMap.GetString(jobMapLicenseKey);
string orgName;
Guid deploymentId;
using (var database = new DiscoDataContext())
{
if (license == null)
license = database.DiscoConfiguration.LicenseKey;
orgName = database.DiscoConfiguration.OrganisationName;
deploymentId = Guid.Parse(database.DiscoConfiguration.DeploymentId);
}
if (!string.IsNullOrWhiteSpace(license))
{
var result = ValidateLicense(deploymentId, orgName, license, true, out var infrastructureError);
string infrastructureError2 = null;
if (result == null)
result = ValidateLicense(deploymentId, orgName, license, false, out infrastructureError2);
if (result == null)
{
var error = $"Validation failed. {infrastructureError ?? infrastructureError2}";
Status.SetTaskException(new Exception(error));
}
else
{
if (result.IsValid)
{
using (var database = new DiscoDataContext())
{
database.DiscoConfiguration.LicenseKey = license;
database.DiscoConfiguration.LicenseExpiresOn = result.ExpiresOn;
database.DiscoConfiguration.LicenseError = null;
database.SaveChanges();
}
Status.UpdateStatus(100, "License validated");
}
else
{
var error = result.ErrorMessage ?? "Validation failed";
Status.SetTaskException(new Exception(error));
}
}
}
}
private LicenseResponseV1 ValidateLicense(Guid deploymentId, string organisationName, string license, bool useProxy, out string infrastructureError)
{
Status.UpdateStatus(10, $"Validating license for {organisationName}");
var appVersion = typeof(LicenseValidationTask).Assembly.GetName().Version.ToString(4);
var updateUrl = $"{DiscoServiceHelpers.ServicesUrl}API/License/V1";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(updateUrl);
// Fix for Proxy Servers which don't support KeepAlive
request.KeepAlive = false;
if (!useProxy)
request.Proxy = new WebProxy();
request.ContentType = "application/x-www-form-urlencoded";
request.Method = WebRequestMethods.Http.Post;
request.UserAgent = $"Disco/{appVersion} (License)";
using (var requestStream = request.GetRequestStream())
{
using (var writer = new StreamWriter(requestStream, Encoding.GetEncoding(28591)))
{
writer.Write("deploymentId=");
writer.Write(Uri.EscapeDataString(deploymentId.ToString()));
writer.Write($"&license={Uri.EscapeDataString(license)}");
}
}
Status.UpdateStatus(50, "Waiting for validation response");
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
Status.UpdateStatus(90, "Reading validation response");
string validationJson;
LicenseResponseV1 updateResult;
using (var responseStream = response.GetResponseStream())
{
using (var responseReader = new StreamReader(responseStream))
{
validationJson = responseReader.ReadToEnd();
}
}
updateResult = JsonConvert.DeserializeObject<LicenseResponseV1>(validationJson);
infrastructureError = null;
return updateResult;
}
else
{
infrastructureError = $"Server responded with: [{response.StatusCode}] {response.StatusDescription}";
return null;
}
}
}
private class LicenseResponseV1
{
public bool IsValid { get; set; }
public DateTime? ValidOn { get; set; }
public DateTime? ExpiresOn { get; set; }
public string ErrorMessage { get; set; }
}
}
}
@@ -0,0 +1,79 @@
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Microsoft.Web.Administration;
using Microsoft.Win32;
using Quartz;
using System;
using System.Linq;
using System.Text;
namespace Disco.Services.Interop.DiscoServices
{
public class PreserveIisBindingsTask : ScheduledTask
{
private const string DiscoRegistryKey = @"SOFTWARE\Disco";
public override string TaskName { get { return "Disco ICT - Preserve IIS Bindings"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
TriggerBuilder triggerBuilder = TriggerBuilder.Create()
.StartAt(DateTimeOffset.Now.AddMinutes(10));
ScheduleTask(triggerBuilder);
}
protected override void ExecuteTask()
{
// retrieve IIS bindings
var bindings = GetWebsiteBindings();
if (bindings == null || !bindings.Any())
{
ScheduledTasksLog.LogScheduledTaskInformation(Status.TaskName, Status.SessionId, "Bindings for IIS Web Site 'Disco' not found");
return;
}
using (var key = Registry.LocalMachine.CreateSubKey(DiscoRegistryKey))
{
key.SetValue("WebsiteBindings", bindings, RegistryValueKind.MultiString);
}
}
private string[] GetWebsiteBindings()
{
using (var manager = new ServerManager())
{
var site = manager.Sites["Disco"];
if (site == null)
return null;
var bindings = site.Bindings;
var sb = new StringBuilder();
var result = new string[bindings.Count];
for (int i = 0; i < bindings.Count; i++)
{
var binding = bindings[i];
sb.Append(binding.BindingInformation);
sb.Append(';');
sb.Append(binding.Protocol);
if (string.Equals(binding.Protocol, "https", StringComparison.OrdinalIgnoreCase))
{
sb.Append(';');
sb.Append(Convert.ToBase64String(binding.CertificateHash));
sb.Append(';');
sb.Append(binding.CertificateStoreName);
}
result[i] = sb.ToString();
sb.Clear();
}
return result;
}
}
}
}
+119 -17
View File
@@ -4,6 +4,7 @@ using Disco.Models.Repository;
using Disco.Services.Authorization; using Disco.Services.Authorization;
using Disco.Services.Logging; using Disco.Services.Logging;
using Disco.Services.Plugins; using Disco.Services.Plugins;
using Disco.Services.Plugins.Features.InsuranceProvider;
using Disco.Services.Plugins.Features.RepairProvider; using Disco.Services.Plugins.Features.RepairProvider;
using Disco.Services.Plugins.Features.WarrantyProvider; using Disco.Services.Plugins.Features.WarrantyProvider;
using Disco.Services.Users; using Disco.Services.Users;
@@ -63,13 +64,34 @@ namespace Disco.Services
return (!j.ClosedDate.HasValue) && j.DeviceHeld.HasValue && return (!j.ClosedDate.HasValue) && j.DeviceHeld.HasValue &&
!j.DeviceReadyForReturn.HasValue && !j.DeviceReturnedDate.HasValue; !j.DeviceReadyForReturn.HasValue && !j.DeviceReturnedDate.HasValue;
} }
public static void OnDeviceReadyForReturn(this Job j, User Technician) public static void OnDeviceReadyForReturn(this Job j, DiscoDataContext Database, User Technician)
{ {
if (!j.CanDeviceReadyForReturn()) if (!j.CanDeviceReadyForReturn())
throw new InvalidOperationException("Device Ready for Return was Denied"); throw new InvalidOperationException("Device Ready for Return was Denied");
j.DeviceReadyForReturn = DateTime.Now; j.DeviceReadyForReturn = DateTime.Now;
j.DeviceReadyForReturnTechUserId = Technician.UserId; j.DeviceReadyForReturnTechUserId = Technician.UserId;
// Evaluate OnDeviceReadyForReturnExpression Expression
try
{
var result = j.EvaluateOnDeviceReadyForReturnExpression(Database);
if (!string.IsNullOrWhiteSpace(result))
{
var jl = new JobLog()
{
Job = j,
TechUser = Technician,
Timestamp = DateTime.Now,
Comments = result
};
Database.JobLogs.Add(jl);
}
}
catch (Exception ex)
{
SystemLog.LogException("Job Expression - OnDeviceReadyForReturnExpression", ex);
}
} }
#endregion #endregion
@@ -160,19 +182,21 @@ namespace Disco.Services
public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, List<JobAttachment> SendAttachments, PluginFeatureManifest WarrantyProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> WarrantyProviderProperties) public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, List<JobAttachment> SendAttachments, PluginFeatureManifest WarrantyProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> WarrantyProviderProperties)
{ {
if (!j.CanLogWarranty()) if (!j.CanLogWarranty())
throw new InvalidOperationException("Log Warranty was Denied"); throw new InvalidOperationException("Lodge Warranty was Denied");
PublishJobResult publishJobResult = null; PublishJobResult publishJobResult = null;
using (WarrantyProviderFeature WarrantyProvider = WarrantyProviderDefinition.CreateInstance<WarrantyProviderFeature>()) using (WarrantyProviderFeature warrantyProvider = WarrantyProviderDefinition.CreateInstance<WarrantyProviderFeature>())
{ {
if (SendAttachments != null && SendAttachments.Count > 0) var warrantyProvider2 = warrantyProvider as WarrantyProvider2Feature;
if (warrantyProvider2 == null && SendAttachments != null && SendAttachments.Count > 0)
{ {
publishJobResult = DiscoServicesJobs.Publish( publishJobResult = DiscoServicesJobs.Publish(
Database, Database,
j, j,
TechUser, TechUser,
WarrantyProvider.WarrantyProviderId, warrantyProvider.WarrantyProviderId,
null, null,
FaultDescription, FaultDescription,
SendAttachments, SendAttachments,
@@ -194,10 +218,14 @@ namespace Disco.Services
else else
submitDescription = string.Concat(FaultDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition)); submitDescription = string.Concat(FaultDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition));
string providerRef = WarrantyProvider.SubmitJob(Database, j, Address, TechUser, submitDescription, WarrantyProviderProperties); string providerRef;
if (warrantyProvider2 != null)
providerRef = warrantyProvider2.SubmitJob(Database, j, Address, TechUser, FaultDescription, SendAttachments, WarrantyProviderProperties);
else
providerRef = warrantyProvider.SubmitJob(Database, j, Address, TechUser, submitDescription, WarrantyProviderProperties);
j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now; j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now;
j.JobMetaWarranty.ExternalName = WarrantyProvider.WarrantyProviderId; j.JobMetaWarranty.ExternalName = warrantyProvider.WarrantyProviderId;
if (providerRef != null && providerRef.Length > 100) if (providerRef != null && providerRef.Length > 100)
j.JobMetaWarranty.ExternalReference = providerRef.Substring(0, 100); j.JobMetaWarranty.ExternalReference = providerRef.Substring(0, 100);
@@ -210,7 +238,7 @@ namespace Disco.Services
JobId = j.Id, JobId = j.Id,
TechUserId = TechUser.UserId, TechUserId = TechUser.UserId,
Timestamp = DateTime.Now, Timestamp = DateTime.Now,
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) 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); Database.JobLogs.Add(jobLog);
@@ -227,7 +255,7 @@ namespace Disco.Services
public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, 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()) if (!j.CanLogWarranty())
throw new InvalidOperationException("Log Warranty was Denied"); throw new InvalidOperationException("Lodge Warranty was Denied");
j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now; j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now;
j.JobMetaWarranty.ExternalName = ManualProviderName; j.JobMetaWarranty.ExternalName = ManualProviderName;
@@ -347,6 +375,7 @@ namespace Disco.Services
#endregion #endregion
#region Insurance Claim Form Sent #region Insurance Claim Form Sent
[Obsolete("Use Log Insurance instead")]
public static bool CanInsuranceClaimFormSent(this Job j) public static bool CanInsuranceClaimFormSent(this Job j)
{ {
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent)) if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent))
@@ -356,6 +385,7 @@ namespace Disco.Services
j.JobMetaNonWarranty.IsInsuranceClaim && j.JobMetaNonWarranty.IsInsuranceClaim &&
!j.JobMetaInsurance.ClaimFormSentDate.HasValue; !j.JobMetaInsurance.ClaimFormSentDate.HasValue;
} }
[Obsolete("Use Log Insurance instead")]
public static void OnInsuranceClaimFormSent(this Job j) public static void OnInsuranceClaimFormSent(this Job j)
{ {
if (!j.CanInsuranceClaimFormSent()) if (!j.CanInsuranceClaimFormSent())
@@ -382,19 +412,21 @@ namespace Disco.Services
public static void OnLogRepair(this Job j, DiscoDataContext Database, string RepairDescription, List<JobAttachment> SendAttachments, PluginFeatureManifest RepairProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> RepairProviderProperties) public static void OnLogRepair(this Job j, DiscoDataContext Database, string RepairDescription, List<JobAttachment> SendAttachments, PluginFeatureManifest RepairProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> RepairProviderProperties)
{ {
if (!j.CanLogRepair()) if (!j.CanLogRepair())
throw new InvalidOperationException("Log Repair was Denied"); throw new InvalidOperationException("Lodge Repair was Denied");
PublishJobResult publishJobResult = null; PublishJobResult publishJobResult = null;
using (RepairProviderFeature RepairProvider = RepairProviderDefinition.CreateInstance<RepairProviderFeature>()) using (RepairProviderFeature repairProvider = RepairProviderDefinition.CreateInstance<RepairProviderFeature>())
{ {
if (SendAttachments != null && SendAttachments.Count > 0) var repairProvider2 = repairProvider as RepairProvider2Feature;
if (repairProvider2 == null && SendAttachments != null && SendAttachments.Count > 0)
{ {
publishJobResult = DiscoServicesJobs.Publish( publishJobResult = DiscoServicesJobs.Publish(
Database, Database,
j, j,
TechUser, TechUser,
RepairProvider.ProviderId, repairProvider.ProviderId,
null, null,
RepairDescription, RepairDescription,
SendAttachments, SendAttachments,
@@ -416,10 +448,14 @@ namespace Disco.Services
else else
submitDescription = string.Concat(RepairDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, RepairProviderDefinition)); submitDescription = string.Concat(RepairDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, RepairProviderDefinition));
string providerRef = RepairProvider.SubmitJob(Database, j, Address, TechUser, submitDescription, RepairProviderProperties); string providerRef;
if (repairProvider2 != null)
providerRef = repairProvider2.SubmitJob(Database, j, Address, TechUser, submitDescription, SendAttachments, RepairProviderProperties);
else
providerRef = repairProvider.SubmitJob(Database, j, Address, TechUser, submitDescription, RepairProviderProperties);
j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now; j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now;
j.JobMetaNonWarranty.RepairerName = RepairProvider.ProviderId; j.JobMetaNonWarranty.RepairerName = repairProvider.ProviderId;
if (providerRef != null && providerRef.Length > 100) if (providerRef != null && providerRef.Length > 100)
j.JobMetaNonWarranty.RepairerReference = providerRef.Substring(0, 100); j.JobMetaNonWarranty.RepairerReference = providerRef.Substring(0, 100);
@@ -432,7 +468,7 @@ namespace Disco.Services
JobId = j.Id, JobId = j.Id,
TechUserId = TechUser.UserId, TechUserId = TechUser.UserId,
Timestamp = DateTime.Now, Timestamp = DateTime.Now,
Comments = string.Format("# Repair Request Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n```{3}```", RepairProvider.Manifest.Name, Address.Name, providerRef, RepairDescription) Comments = string.Format("# Repair Request Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n```{3}```", repairProvider.Manifest.Name, Address.Name, providerRef, RepairDescription)
}; };
Database.JobLogs.Add(jobLog); Database.JobLogs.Add(jobLog);
@@ -449,7 +485,7 @@ namespace Disco.Services
public static void OnLogRepair(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, OrganisationAddress Address, User TechUser) public static void OnLogRepair(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, OrganisationAddress Address, User TechUser)
{ {
if (!j.CanLogRepair()) if (!j.CanLogRepair())
throw new InvalidOperationException("Log Repair was Denied"); throw new InvalidOperationException("Lodge Repair was Denied");
j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now; j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now;
j.JobMetaNonWarranty.RepairerName = ManualProviderName; j.JobMetaNonWarranty.RepairerName = ManualProviderName;
@@ -490,6 +526,72 @@ namespace Disco.Services
} }
#endregion #endregion
#region Log Insurance
public static bool CanLogInsurance(this Job j)
{
if (!UserService.CurrentAuthorization.HasAny(Claims.Job.Actions.LogInsurance, Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent))
return false;
return j.JobTypeId == JobType.JobTypeIds.HNWar &&
j.DeviceSerialNumber != null &&
j.JobMetaNonWarranty.IsInsuranceClaim &&
!j.JobMetaInsurance.ClaimFormSentDate.HasValue;
}
public static void OnLogInsurance(this Job j, DiscoDataContext database, List<JobAttachment> attachments, PluginFeatureManifest providerDefinition, OrganisationAddress address, User techUser, Dictionary<string, string> providerProperties)
{
if (!j.CanLogInsurance())
throw new InvalidOperationException("Lodge Insurance was Denied");
using (var provider = providerDefinition.CreateInstance<InsuranceProviderFeature>())
{
var providerRef = provider.SubmitJob(database, j, address, techUser, attachments, providerProperties);
j.JobMetaInsurance.Insurer = provider.ProviderId;
j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now;
j.JobMetaInsurance.ClaimFormSentUserId = techUser.UserId;
if (providerRef != null && providerRef.Length > 200)
j.JobMetaInsurance.InsurerReference = providerRef.Substring(0, 200);
else
j.JobMetaInsurance.InsurerReference = providerRef;
// Write Log
var jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = techUser.UserId,
Timestamp = DateTime.Now,
Comments = $"# Insurance Claim Submitted\r\nProvider: **{provider.Manifest.Name}**\r\nAddress: **{address.Name}**\r\nReference: **{providerRef}**",
};
database.JobLogs.Add(jobLog);
}
}
public static void OnLogInsurance(this Job j, DiscoDataContext database, string manualProviderName, string manualProviderReference, OrganisationAddress address, User techUser)
{
if (!j.CanLogInsurance())
throw new InvalidOperationException("Lodge Insurance was Denied");
j.JobMetaInsurance.Insurer = manualProviderName;
j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now;
j.JobMetaInsurance.ClaimFormSentUserId = techUser.UserId;
if (manualProviderReference != null && manualProviderReference.Length > 200)
j.JobMetaInsurance.InsurerReference = manualProviderReference.Substring(0, 200);
else
j.JobMetaInsurance.InsurerReference = manualProviderReference;
// Write Log
JobLog jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = techUser.UserId,
Timestamp = DateTime.Now,
Comments = $"# Manual Insurance Request Submitted\r\nProvider: **{manualProviderName}**\r\nAddress: **{address.Name}**\r\nReference: **{manualProviderReference ?? "<none>"}**",
};
database.JobLogs.Add(jobLog);
}
#endregion
#region Close #region Close
public static void OnCloseNormally(this Job j, DiscoDataContext Database, User Technician) public static void OnCloseNormally(this Job j, DiscoDataContext Database, User Technician)
{ {
+15
View File
@@ -407,6 +407,21 @@ namespace Disco.Services
return null; return null;
} }
public static string EvaluateOnDeviceReadyForReturnExpression(this Job job, DiscoDataContext Database)
{
if (!string.IsNullOrEmpty(Database.DiscoConfiguration.JobPreferences.OnDeviceReadyForReturnExpression))
{
Expression compiledExpression = Jobs.Jobs.OnDeviceReadyForReturnExpressionFromCache(Database);
IDictionary evaluatorVariables = Expression.StandardVariables(null, Database, job.OpenedTechUser, DateTime.Now, null, job);
object result = compiledExpression.EvaluateFirst<object>(job, evaluatorVariables);
if (result == null)
return null;
else
return result.ToString();
}
return null;
}
public static string EvaluateOnCloseExpression(this Job job, DiscoDataContext Database) public static string EvaluateOnCloseExpression(this Job job, DiscoDataContext Database)
{ {
if (!string.IsNullOrEmpty(Database.DiscoConfiguration.JobPreferences.OnCloseExpression)) if (!string.IsNullOrEmpty(Database.DiscoConfiguration.JobPreferences.OnCloseExpression))
+10
View File
@@ -131,6 +131,16 @@ namespace Disco.Services.Jobs
ExpressionCache.InvalidateSingleCache("Job_OnCreateExpression"); ExpressionCache.InvalidateSingleCache("Job_OnCreateExpression");
} }
public static Expression OnDeviceReadyForReturnExpressionFromCache(DiscoDataContext Database)
{
return ExpressionCache.GetOrCreateSingleExpressions("Job_OnDeviceReadyForReturnExpression", () => Expression.TokenizeSingleDynamic(null, Database.DiscoConfiguration.JobPreferences.OnDeviceReadyForReturnExpression, 0));
}
public static void OnDeviceReadyForReturnExpressionInvalidateCache()
{
ExpressionCache.InvalidateSingleCache("Job_OnDeviceReadyForReturnExpression");
}
public static Expression OnCloseExpressionFromCache(DiscoDataContext Database) public static Expression OnCloseExpressionFromCache(DiscoDataContext Database)
{ {
return ExpressionCache.GetOrCreateSingleExpressions("Job_OnCloseExpression", () => Expression.TokenizeSingleDynamic(null, Database.DiscoConfiguration.JobPreferences.OnCloseExpression, 0)); return ExpressionCache.GetOrCreateSingleExpressions("Job_OnCloseExpression", () => Expression.TokenizeSingleDynamic(null, Database.DiscoConfiguration.JobPreferences.OnCloseExpression, 0));
+6
View File
@@ -2,6 +2,7 @@
using Disco.Data.Repository; using Disco.Data.Repository;
using Disco.Models.Services.Messaging; using Disco.Models.Services.Messaging;
using System; using System;
using System.IO;
using System.Net; using System.Net;
using System.Net.Mail; using System.Net.Mail;
@@ -98,6 +99,11 @@ namespace Disco.Services.Messaging
foreach (var recipient in email.BCC) foreach (var recipient in email.BCC)
message.Bcc.Add(recipient); message.Bcc.Add(recipient);
} }
if (email.Attachments.Count > 0)
{
foreach (var attachment in email.Attachments)
message.Attachments.Add(new Attachment(new MemoryStream(attachment.Data), attachment.Name, attachment.MediaType));
}
using (var smtpClient = new SmtpClient(smtpServer, smtpPort)) using (var smtpClient = new SmtpClient(smtpServer, smtpPort))
{ {
@@ -0,0 +1,92 @@
using Disco.Data.Repository;
using Disco.Models.BI.Config;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace Disco.Services.Plugins.Features.InsuranceProvider
{
[PluginFeatureCategory(DisplayName = "Insurance Providers")]
public abstract class InsuranceProviderFeature : PluginFeature
{
/// <summary>
/// The insurer identifier. Used to link this provider to any <see cref="JobMetaInsurance.Insurer"/>. This identifier is used to automatically set the Insurer when a job is submitted using this plugin.
/// </summary>
public abstract string ProviderId { get; }
#region Job Submission
/// <summary>
/// Called when a user selects this plugin to submit the insurance claim and allows a plugin to inject a View to collect additional information.
/// </summary>
/// <returns>A Tuple consisting of the Razor View type and a View Model</returns>
public virtual Tuple<Type, dynamic> SubmitJobBegin(DiscoDataContext database, Controller controller, Job job, OrganisationAddress address, User techUser)
{
return null;
}
/// <summary>
/// Called after the RepairDescription is completed and allows the plugin to parse any data collected from SubmitJobBegin.
/// </summary>
/// <returns>A Dictionary of key/value items which are persisted throughout the submission and passed into the final SubmitJob method.</returns>
public virtual Dictionary<string, string> SubmitJobParseProperties(DiscoDataContext database, FormCollection form, Controller controller, Job job, OrganisationAddress address, User techUser)
{
return null;
}
/// <summary>
/// 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.
/// </summary>
/// <returns>A Dictionary of key/value items which contain all information which will be disclosed to the plugin provider.</returns>
public abstract Dictionary<string, string> SubmitJobDiscloseInfo(DiscoDataContext database, Job job, OrganisationAddress address, User techUser, Dictionary<string, string> providerProperties);
/// <summary>
/// Called when the plugin should submit the job to the external party.
/// </summary>
/// <returns>A reference number/identifier from the external party which is stored in <see cref="JobMetaInsurance.InsurerReference"/></returns>
public abstract string SubmitJob(DiscoDataContext database, Job job, OrganisationAddress address, User techUser, List<JobAttachment> attachments, Dictionary<string, string> providerProperties);
#endregion
#region Job Details
/// <summary>
/// <see cref="true"/> when additional Job Details are supported by the external party. When <see cref="true"/>, JobDetailsViewModel must be implemented.
/// </summary>
public abstract bool JobDetailsSupported { get; }
/// <summary>
/// Called when a job's insurance information is shown. Allows a plugin to inject a View to display additional information.
/// </summary>
/// <returns>A Tuple consisting of the Razor View type and a View Model</returns>
public virtual Tuple<Type, dynamic> JobDetails(DiscoDataContext database, Controller controller, Job job)
{
return null;
}
#endregion
public static PluginFeatureManifest FindPluginFeature(string pluginIdOrInsuranceProviderId)
{
var defs = Plugins.GetPluginFeatures(typeof(InsuranceProviderFeature));
var def = defs.FirstOrDefault(d => d.PluginManifest.Id.Equals(pluginIdOrInsuranceProviderId, StringComparison.OrdinalIgnoreCase));
if (def != null)
return def;
else
foreach (var d in defs)
{
using (var providerInstance = d.CreateInstance<InsuranceProviderFeature>())
{
if (providerInstance.ProviderId != null && providerInstance.ProviderId.Equals(pluginIdOrInsuranceProviderId, StringComparison.OrdinalIgnoreCase))
{
return d;
}
}
}
return null;
}
}
}
@@ -0,0 +1,12 @@
using System;
namespace Disco.Services.Plugins.Features.InsuranceProvider
{
public class InsuranceProviderSubmitJobException : Exception
{
public InsuranceProviderSubmitJobException(string message)
: base(message)
{
}
}
}
@@ -0,0 +1,20 @@
using Disco.Data.Repository;
using Disco.Models.BI.Config;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
namespace Disco.Services.Plugins.Features.RepairProvider
{
[PluginFeatureCategory(DisplayName = "Repair Providers")]
public abstract class RepairProvider2Feature : RepairProviderFeature
{
public override sealed string SubmitJob(DiscoDataContext Database, Job Job, OrganisationAddress Address, User TechUser, string RepairDescription, Dictionary<string, string> ProviderProperties)
{
throw new NotSupportedException();
}
public abstract string SubmitJob(DiscoDataContext database, Job job, OrganisationAddress address, User techUser, string description, List<JobAttachment> attachments, Dictionary<string, string> providerProperties);
}
}
@@ -0,0 +1,19 @@
using Disco.Data.Repository;
using Disco.Models.BI.Config;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
namespace Disco.Services.Plugins.Features.WarrantyProvider
{
[PluginFeatureCategory(DisplayName = "Warranty Providers")]
public abstract class WarrantyProvider2Feature : WarrantyProviderFeature
{
public override sealed string SubmitJob(DiscoDataContext Database, Job Job, OrganisationAddress Address, User TechUser, string FaultDescription, Dictionary<string, string> WarrantyProviderProperties)
{
throw new NotSupportedException();
}
public abstract string SubmitJob(DiscoDataContext database, Job job, OrganisationAddress address, User techUser, string description, List<JobAttachment> attachments, Dictionary<string, string> providerProperties);
}
}
+2 -1
View File
@@ -530,6 +530,7 @@ namespace Disco.Services.Plugins
public void LogWarning(string Message) public void LogWarning(string Message)
{ {
LogWarning(Message, null); LogWarning(Message, null);
PluginsLog.LogPluginWarning(this, Message);
} }
public void LogWarning(string MessageFormat, params object[] Args) public void LogWarning(string MessageFormat, params object[] Args)
{ {
@@ -537,7 +538,7 @@ namespace Disco.Services.Plugins
} }
public void LogMessage(string Message) public void LogMessage(string Message)
{ {
LogMessage(Message, null); PluginsLog.LogPluginMessage(this, Message);
} }
public void LogMessage(string MessageFormat, params object[] Args) public void LogMessage(string MessageFormat, params object[] Args)
{ {
+19 -4
View File
@@ -179,6 +179,15 @@ namespace Disco.Services.Plugins
return new HttpStatusCodeResult(System.Net.HttpStatusCode.OK, description); return new HttpStatusCodeResult(System.Net.HttpStatusCode.OK, description);
} }
public ActionResult BadRequest()
{
return new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest);
}
public ActionResult BadRequest(string description)
{
return new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest, description);
}
#endregion #endregion
#region Content #region Content
@@ -262,11 +271,17 @@ namespace Disco.Services.Plugins
} }
public ActionResult RedirectToPluginAction(string PluginAction) public ActionResult RedirectToPluginAction(string PluginAction)
{ {
if (string.IsNullOrEmpty(PluginAction)) return RedirectToPluginAction(PluginAction, null);
throw new ArgumentNullException("PluginAction"); }
public ActionResult RedirectToPluginAction(string pluginAction, object routeValues)
{
if (string.IsNullOrEmpty(pluginAction))
throw new ArgumentNullException(nameof(pluginAction));
var routeValues = new RouteValueDictionary(new { PluginId = Manifest.Id, PluginAction = PluginAction }); var routeValueDictionary = new RouteValueDictionary(routeValues);
string pluginActionUrl = UrlHelper.GenerateUrl("Plugin", null, null, routeValues, RouteTable.Routes, HostController.Request.RequestContext, false); routeValueDictionary.Add("PluginId", Manifest.Id);
routeValueDictionary.Add("PluginAction", pluginAction);
string pluginActionUrl = UrlHelper.GenerateUrl("Plugin", null, null, routeValueDictionary, RouteTable.Routes, HostController.Request.RequestContext, false);
return new RedirectResult(pluginActionUrl, false); return new RedirectResult(pluginActionUrl, false);
} }
@@ -134,6 +134,7 @@ namespace Disco.Services.Plugins
private readonly PluginControllerDescription controllerDescription; private readonly PluginControllerDescription controllerDescription;
private readonly MethodInfo methodInfo; private readonly MethodInfo methodInfo;
private readonly IAuthorizationFilter[] authorizationFilters; private readonly IAuthorizationFilter[] authorizationFilters;
private readonly ActionMethodSelectorAttribute methodSelector;
private readonly PluginParameterDescriptor[] parameterDescriptors; private readonly PluginParameterDescriptor[] parameterDescriptors;
public override string UniqueId { get; } public override string UniqueId { get; }
public override string ActionName { get; } public override string ActionName { get; }
@@ -146,6 +147,7 @@ namespace Disco.Services.Plugins
UniqueId = $"{ControllerDescriptor.UniqueId}_{methodName}"; UniqueId = $"{ControllerDescriptor.UniqueId}_{methodName}";
ActionName = methodName; ActionName = methodName;
authorizationFilters = DiscoverAuthorizationFilters(); authorizationFilters = DiscoverAuthorizationFilters();
methodSelector = DiscoverMethodSelector();
parameterDescriptors = DiscoverParameters(); parameterDescriptors = DiscoverParameters();
} }
@@ -159,6 +161,11 @@ namespace Disco.Services.Plugins
return filters.ToArray(); return filters.ToArray();
} }
private ActionMethodSelectorAttribute DiscoverMethodSelector()
{
return methodInfo.GetCustomAttributes<ActionMethodSelectorAttribute>(true).FirstOrDefault();
}
private PluginParameterDescriptor[] DiscoverParameters() private PluginParameterDescriptor[] DiscoverParameters()
{ {
var methodParams = methodInfo.GetParameters(); var methodParams = methodInfo.GetParameters();
@@ -187,6 +194,9 @@ namespace Disco.Services.Plugins
public ActionResult Execute(PluginWebHandlerController pluginController, ControllerContext controllerContext) public ActionResult Execute(PluginWebHandlerController pluginController, ControllerContext controllerContext)
{ {
if (methodSelector != null && !methodSelector.IsValidForRequest(controllerContext, methodInfo))
return new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest);
var methodParameters = BuildMethodParameters(methodInfo, controllerContext.Controller); var methodParameters = BuildMethodParameters(methodInfo, controllerContext.Controller);
return (ActionResult)methodInfo.Invoke(pluginController, methodParameters); return (ActionResult)methodInfo.Invoke(pluginController, methodParameters);
+1 -1
View File
@@ -237,7 +237,7 @@ namespace Disco.Services.Plugins
if (_PluginManifests == null) if (_PluginManifests == null)
throw new InvalidOperationException("Plugins have not been initialized"); throw new InvalidOperationException("Plugins have not been initialized");
return _PluginManifests.Values.SelectMany(pm => pm.Features).Where(fm => fm.CategoryType.IsAssignableFrom(FeatureCategoryType)).OrderBy(fm => fm.PluginManifest.Name).ToList(); return _PluginManifests.Values.SelectMany(pm => pm.Features).Where(fm => FeatureCategoryType.IsAssignableFrom(fm.CategoryType)).OrderBy(fm => fm.PluginManifest.Name).ToList();
} }
public static List<PluginFeatureManifest> GetPluginFeatures() public static List<PluginFeatureManifest> GetPluginFeatures()
{ {
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.3.23161.0650")] [assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.3.23161.0650")] [assembly: AssemblyFileVersion("2.4.24270.0000")]
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.3.23161.0650")] [assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.3.23161.0650")] [assembly: AssemblyFileVersion("2.4.24270.0000")]
@@ -0,0 +1,44 @@
using Disco.Services.Authorization;
using Disco.Services.Devices.Enrolment;
using Disco.Services.Web;
using System;
using System.Web.Mvc;
namespace Disco.Web.Areas.API.Controllers
{
public partial class EnrollmentController : AuthorizedDatabaseController
{
[HttpPost]
[ValidateAntiForgeryToken]
[DiscoAuthorize(Claims.Device.Actions.EnrolDevices)]
public virtual ActionResult ResolveSessionPending(string sessionId, bool approve, string reason)
{
WindowsDeviceEnrolment.ResolvePendingEnrollment(sessionId, approve, CurrentUser.UserId, reason);
return new HttpStatusCodeResult(200);
}
[HttpPost]
[DiscoAuthorize(Claims.Config.Enrolment.Configure)]
public virtual ActionResult PendingTimeoutMinutes(int PendingTimeoutMinutes)
{
try
{
if (PendingTimeoutMinutes > 0)
{
Database.DiscoConfiguration.Bootstrapper.PendingTimeout = TimeSpan.FromMinutes(PendingTimeoutMinutes);
Database.SaveChanges();
return Json("OK", JsonRequestBehavior.AllowGet);
}
else
{
throw new Exception("The pending timeout must be greater than zero");
}
}
catch (Exception ex)
{
return Json($"Error: {ex.Message}");
}
}
}
}
@@ -1604,12 +1604,13 @@ namespace Disco.Web.Areas.API.Controllers
[DiscoAuthorize(Claims.Job.Properties.DeviceReadyForReturn)] [DiscoAuthorize(Claims.Job.Properties.DeviceReadyForReturn)]
public virtual ActionResult DeviceReadyForReturn(int id, bool redirect) public virtual ActionResult DeviceReadyForReturn(int id, bool redirect)
{ {
Database.Configuration.LazyLoadingEnabled = true;
var j = Database.Jobs.Find(id); var j = Database.Jobs.Find(id);
if (j != null) if (j != null)
{ {
if (j.CanDeviceReadyForReturn()) if (j.CanDeviceReadyForReturn())
{ {
j.OnDeviceReadyForReturn(CurrentUser); j.OnDeviceReadyForReturn(Database, Database.Users.Find(CurrentUser.UserId));
Database.SaveChanges(); Database.SaveChanges();
if (redirect) if (redirect)
@@ -143,6 +143,30 @@ namespace Disco.Web.Areas.API.Controllers
return Json("OK", JsonRequestBehavior.AllowGet); return Json("OK", JsonRequestBehavior.AllowGet);
} }
[DiscoAuthorize(Claims.Config.JobPreferences.Configure)]
public virtual ActionResult UpdateOnDeviceReadyForReturnExpression(string OnDeviceReadyForReturnExpression, bool redirect = false)
{
string expression = null;
if (!string.IsNullOrWhiteSpace(OnDeviceReadyForReturnExpression))
{
expression = OnDeviceReadyForReturnExpression.Trim();
}
if (Database.DiscoConfiguration.JobPreferences.OnDeviceReadyForReturnExpression != expression)
{
Database.DiscoConfiguration.JobPreferences.OnDeviceReadyForReturnExpression = expression;
Database.SaveChanges();
Jobs.OnDeviceReadyForReturnExpressionInvalidateCache();
}
if (redirect)
return RedirectToAction(MVC.Config.JobPreferences.Index());
else
return Json("OK", JsonRequestBehavior.AllowGet);
}
[DiscoAuthorize(Claims.Config.JobPreferences.Configure)] [DiscoAuthorize(Claims.Config.JobPreferences.Configure)]
public virtual ActionResult UpdateOnCloseExpression(string OnCloseExpression, bool redirect = false) public virtual ActionResult UpdateOnCloseExpression(string OnCloseExpression, bool redirect = false)
{ {
@@ -42,6 +42,26 @@ namespace Disco.Web.Areas.API.Controllers
return RedirectToAction(MVC.Config.Logging.TaskStatus(ts.SessionId)); return RedirectToAction(MVC.Config.Logging.TaskStatus(ts.SessionId));
} }
[DiscoAuthorize(Claims.Config.System.Show)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult LicenseCheck(string license)
{
if (string.IsNullOrWhiteSpace(license))
{
Database.DiscoConfiguration.LicenseKey = null;
Database.DiscoConfiguration.LicenseExpiresOn = null;
Database.DiscoConfiguration.LicenseError = null;
Database.SaveChanges();
return RedirectToAction(MVC.Config.SystemConfig.Index());
}
else
{
var ts = Disco.Services.Interop.DiscoServices.LicenseValidationTask.ScheduleNow(license);
ts.SetFinishedUrl(Url.Action(MVC.Config.SystemConfig.Index()));
return RedirectToAction(MVC.Config.Logging.TaskStatus(ts.SessionId));
}
}
[DiscoAuthorize(Claims.Config.System.Show)] [DiscoAuthorize(Claims.Config.System.Show)]
public virtual ActionResult UpdateCheck() public virtual ActionResult UpdateCheck()
{ {
@@ -13,7 +13,8 @@ namespace Disco.Web.Areas.Config.Controllers
{ {
var m = new Models.Enrolment.IndexModel() var m = new Models.Enrolment.IndexModel()
{ {
MacSshUsername = Database.DiscoConfiguration.Bootstrapper.MacSshUsername MacSshUsername = Database.DiscoConfiguration.Bootstrapper.MacSshUsername,
PendingTimeoutMinutes = (int)Database.DiscoConfiguration.Bootstrapper.PendingTimeout.TotalMinutes,
}; };
// UI Extensions // UI Extensions
@@ -19,7 +19,8 @@ namespace Disco.Web.Areas.Config.Controllers
LocationMode = Database.DiscoConfiguration.JobPreferences.LocationMode, LocationMode = Database.DiscoConfiguration.JobPreferences.LocationMode,
LocationList = Database.DiscoConfiguration.JobPreferences.LocationList, LocationList = Database.DiscoConfiguration.JobPreferences.LocationList,
OnCreateExpression = Database.DiscoConfiguration.JobPreferences.OnCreateExpression, OnCreateExpression = Database.DiscoConfiguration.JobPreferences.OnCreateExpression,
OnCloseExpression = Database.DiscoConfiguration.JobPreferences.OnCloseExpression OnDeviceReadyForReturnExpression = Database.DiscoConfiguration.JobPreferences.OnDeviceReadyForReturnExpression,
OnCloseExpression = Database.DiscoConfiguration.JobPreferences.OnCloseExpression,
}; };
// UI Extensions // UI Extensions
@@ -1,13 +1,10 @@
using Disco.Models.UI.Config.Enrolment; using Disco.Models.UI.Config.Enrolment;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Disco.Web.Areas.Config.Models.Enrolment namespace Disco.Web.Areas.Config.Models.Enrolment
{ {
public class IndexModel : ConfigEnrolmentIndexModel public class IndexModel : ConfigEnrolmentIndexModel
{ {
public string MacSshUsername { get; set; } public string MacSshUsername { get; set; }
public int PendingTimeoutMinutes { get; set; }
} }
} }
@@ -20,6 +20,8 @@ namespace Disco.Web.Areas.Config.Models.JobPreferences
[DataType(DataType.MultilineText)] [DataType(DataType.MultilineText)]
public string OnCreateExpression { get; set; } public string OnCreateExpression { get; set; }
[DataType(DataType.MultilineText)] [DataType(DataType.MultilineText)]
public string OnDeviceReadyForReturnExpression { get; set; }
[DataType(DataType.MultilineText)]
public string OnCloseExpression { get; set; } public string OnCloseExpression { get; set; }
public List<KeyValuePair<string, string>> DefaultNoticeboardThemeOptions() public List<KeyValuePair<string, string>> DefaultNoticeboardThemeOptions()
@@ -44,15 +44,14 @@ namespace Disco.Web.Areas.Config.Models.Plugins
} }
} }
public List<Tuple<Type, List<PluginManifest>>> PluginManifestsByCategory public Dictionary<string, List<PluginManifest>> PluginManifestsByCategory
{ {
get get
{ {
if (PluginManifests.Count == 0) if (PluginManifests.Count == 0)
return null; return null;
var pluginsByCategory = new Dictionary<string, List<PluginManifest>>(StringComparer.Ordinal);
List<Tuple<Type, PluginManifest>> pluginsByCategory = new List<Tuple<Type, PluginManifest>>();
foreach (var pluginManifest in PluginManifests) foreach (var pluginManifest in PluginManifests)
{ {
@@ -68,12 +67,17 @@ namespace Disco.Web.Areas.Config.Models.Plugins
else else
categoryType = primaryFeature.CategoryType; categoryType = primaryFeature.CategoryType;
pluginsByCategory.Add(new Tuple<Type, PluginManifest>(categoryType, pluginManifest)); var categoryName = Disco.Services.Plugins.Plugins.PluginFeatureCategoryDisplayName(categoryType);
if (!pluginsByCategory.TryGetValue(categoryName, out var categoryPlugins))
{
categoryPlugins = new List<PluginManifest>();
pluginsByCategory.Add(categoryName, categoryPlugins);
}
categoryPlugins.Add(pluginManifest);
} }
return pluginsByCategory.GroupBy(p => p.Item1) return pluginsByCategory;
.OrderBy(g => g.Key.Name)
.Select(g => new Tuple<Type, List<PluginManifest>>(g.Key, g.Select(pg => pg.Item2).OrderBy(p => p.Name).ToList())).ToList();
} }
} }
} }
@@ -112,6 +112,11 @@ namespace Disco.Web.Areas.Config.Models.SystemConfig
public bool EmailIsConfigured { get; set; } public bool EmailIsConfigured { get; set; }
#endregion #endregion
public ScheduledTaskStatus LicenseValidationRunningStatus { get; set; }
public string License { get; set; }
public DateTime? LicenseExpires { get; set; }
public string LicenseError { get; set; }
public ScheduledTaskStatus UpdateRunningStatus { get; set; } public ScheduledTaskStatus UpdateRunningStatus { get; set; }
public DateTime? UpdateNextScheduled { get; set; } public DateTime? UpdateNextScheduled { get; set; }
public UpdateResponseV2 UpdateLatestResponse { get; set; } public UpdateResponseV2 UpdateLatestResponse { get; set; }
@@ -136,6 +141,10 @@ namespace Disco.Web.Areas.Config.Models.SystemConfig
EmailUsername = config.EmailUsername, EmailUsername = config.EmailUsername,
EmailPassword = null, EmailPassword = null,
EmailIsConfigured = EmailService.IsConfigured, EmailIsConfigured = EmailService.IsConfigured,
License = config.LicenseKey,
LicenseExpires = config.LicenseExpiresOn,
LicenseError = config.LicenseError,
LicenseValidationRunningStatus = LicenseValidationTask.RunningStatus,
UpdateLatestResponse = config.UpdateLastCheckResponse, UpdateLatestResponse = config.UpdateLastCheckResponse,
UpdateRunningStatus = UpdateQueryTask.RunningStatus, UpdateRunningStatus = UpdateQueryTask.RunningStatus,
UpdateNextScheduled = UpdateQueryTask.NextScheduled, UpdateNextScheduled = UpdateQueryTask.NextScheduled,
@@ -84,9 +84,9 @@
} }
@if (Authorization.Has(Claims.Config.Enrolment.Show)) @if (Authorization.Has(Claims.Config.Enrolment.Show))
{ {
<i class="fa fa-cog"></i>@Html.ActionLinkClass("Enrolment", MVC.Config.Enrolment.Index(), "config") <i class="fa fa-cog"></i>@Html.ActionLinkClass("Enrollment", MVC.Config.Enrolment.Index(), "config")
<div class="pageMenuBlurb"> <div class="pageMenuBlurb">
Configure Enrolment settings including secure credentials. Configure Enrollment settings including secure credentials.
</div> </div>
} }
</div> </div>
@@ -592,14 +592,14 @@ WriteLiteral("></i>");
#line hidden #line hidden
#line 87 "..\..\Areas\Config\Views\Config\Index.cshtml" #line 87 "..\..\Areas\Config\Views\Config\Index.cshtml"
Write(Html.ActionLinkClass("Enrolment", MVC.Config.Enrolment.Index(), "config")); Write(Html.ActionLinkClass("Enrollment", MVC.Config.Enrolment.Index(), "config"));
#line default #line default
#line hidden #line hidden
#line 87 "..\..\Areas\Config\Views\Config\Index.cshtml" #line 87 "..\..\Areas\Config\Views\Config\Index.cshtml"
#line default #line default
@@ -608,8 +608,8 @@ WriteLiteral(" <div");
WriteLiteral(" class=\"pageMenuBlurb\""); WriteLiteral(" class=\"pageMenuBlurb\"");
WriteLiteral(">\r\n Configure Enrolment settings including secure cred" + WriteLiteral(">\r\n Configure Enrollment settings including secure cre" +
"entials.\r\n </div>\r\n"); "dentials.\r\n </div>\r\n");
#line 91 "..\..\Areas\Config\Views\Config\Index.cshtml" #line 91 "..\..\Areas\Config\Views\Config\Index.cshtml"
@@ -961,14 +961,14 @@ WriteLiteral(" class=\"fa fa-cloud-download info\"");
WriteLiteral("></i>\r\n <div>An updated version of Disco is available</div>\r\n <a"); WriteLiteral("></i>\r\n <div>An updated version of Disco is available</div>\r\n <a");
WriteAttribute("href", Tuple.Create(" href=\"", 8211), Tuple.Create("\"", 8247) WriteAttribute("href", Tuple.Create(" href=\"", 8213), Tuple.Create("\"", 8249)
#line 155 "..\..\Areas\Config\Views\Config\Index.cshtml" #line 155 "..\..\Areas\Config\Views\Config\Index.cshtml"
, Tuple.Create(Tuple.Create("", 8218), Tuple.Create<System.Object, System.Int32>(Model.UpdateResponse.UrlLink , Tuple.Create(Tuple.Create("", 8220), Tuple.Create<System.Object, System.Int32>(Model.UpdateResponse.UrlLink
#line default #line default
#line hidden #line hidden
, 8218), false) , 8220), false)
); );
WriteLiteral(" class=\"button small alert\""); WriteLiteral(" class=\"button small alert\"");
@@ -5,20 +5,98 @@
var canConfig = Authorization.Has(Claims.Config.Enrolment.Configure); var canConfig = Authorization.Has(Claims.Config.Enrolment.Configure);
var canShowStatus = Authorization.Has(Claims.Config.Enrolment.ShowStatus); var canShowStatus = Authorization.Has(Claims.Config.Enrolment.ShowStatus);
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrolment"); ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrollment");
} }
<div class="form" style="width: 530px;"> <div class="form" style="width: 530px;">
<h2>Apple Mac Secure Enrol</h2>
<table> <table>
<tr> <tr>
<th>Username: <th>
Pending Timeout:
</th> </th>
<td>@if (canConfig) <td>
@if (canConfig)
{ {
@Html.TextBoxFor(model => model.MacSshUsername) @Html.TextBoxFor(model => model.PendingTimeoutMinutes, new { type = "number", min = "1" })
@AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxLoader()
<script type="text/javascript"> <span> minutes <span class="smallText">(default: 30)</span></span>
<script type="text/javascript">
$(function () {
var $DOM = $('#PendingTimeoutMinutes');
var $DOMAjaxSave = $DOM.next('.ajaxSave');
$DOM
.watermark('Minutes')
.focus(function () { $DOM.select() })
.keydown(function (e) {
$DOMAjaxSave.show();
if (e.which == 13) {
$(this).blur();
}
}).blur(function () {
$DOMAjaxSave.hide();
})
.change(function () {
$DOMAjaxSave.hide();
var $ajaxLoading = $DOMAjaxSave.next('.ajaxLoading').show();
var data = { PendingTimeoutMinutes: parseInt($DOM.val()) };
if (data.PendingTimeoutMinutes <= 0) {
alert('Pending Timeout must be greater than zero');
$ajaxLoading.hide();
return;
} else {
$.ajax({
url: '@Url.Action(MVC.API.Enrollment.PendingTimeoutMinutes())',
dataType: 'json',
method: 'POST',
data: data,
success: function (d) {
if (d == 'OK') {
$ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
} else {
$ajaxLoading.hide();
alert('Unable to update pending timeout: ' + d);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Unable to update pending timeout: ' + textStatus);
$ajaxLoading.hide();
}
});
}
});
});
</script>
}
else
{
@TimeSpan.FromMinutes(Model.PendingTimeoutMinutes)
}
</td>
</tr>
<tr>
<td colspan="2">
<span class="smallText">
If a device enrollment is not automatically approved it will remain pending until the timeout is reached.
Pending enrollments can be approved manually from the Enrollment Status page.
</span>
</td>
</tr>
</table>
</div>
<div class="form" style="width: 530px; margin-top: 15px">
<h2>Apple Mac Secure Enroll</h2>
<table>
<tr>
<th>
Username:
</th>
<td>
@if (canConfig)
{
@Html.TextBoxFor(model => model.MacSshUsername)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
var $DOM = $('#MacSshUsername'); var $DOM = $('#MacSshUsername');
var $DOMAjaxSave = $DOM.next('.ajaxSave'); var $DOMAjaxSave = $DOM.next('.ajaxSave');
@@ -56,31 +134,33 @@
}); });
}); });
}); });
</script> </script>
} }
else else
{ {
if (string.IsNullOrEmpty(Model.MacSshUsername)) if (string.IsNullOrEmpty(Model.MacSshUsername))
{ {
<span class="smallMessage">&lt;None Specified&gt;</span> <span class="smallMessage">&lt;None Specified&gt;</span>
} }
else else
{ {
@Model.MacSshUsername @Model.MacSshUsername
} }
} }
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Password: <th>
Password:
</th> </th>
<td>@if (canConfig) <td>
@if (canConfig)
{ {
<input id="MacSshPassword" type="password" /> <input id="MacSshPassword" type="password" />
@AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxLoader()
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
var $DOM = $('#MacSshPassword'); var $DOM = $('#MacSshPassword');
var $DOMAjaxSave = $DOM.next('.ajaxSave'); var $DOMAjaxSave = $DOM.next('.ajaxSave');
@@ -118,32 +198,36 @@
}); });
}); });
}); });
</script> </script>
} }
else else
{ {
<text>********</text> <text>********</text>
} }
</td> </td>
</tr> </tr>
<tr> <tr>
<td colspan="2"> <td colspan="2">
<span class="smallText"><strong>Instructions:</strong> The above credentials must be <span class="smallText">
able to connect to the requesting Apple Mac client via <a target="_blank" href="http://en.wikipedia.org/wiki/Secure_Shell">SSH</a>. Enter/Script the following command:</span> <strong>Instructions:</strong> The above credentials must be
able to connect to the requesting Apple Mac client via <a target="_blank" href="http://en.wikipedia.org/wiki/Secure_Shell">SSH</a>. Enter/Script the following command:
</span>
<div class="code"> <div class="code">
curl&nbsp;<a target="_blank" href="http://disco:9292/Services/Client/Unauthenticated/MacSecureEnrol">http://disco:9292/Services/Client/Unauthenticated/MacSecureEnrol</a> curl&nbsp;<a target="_blank" href="http://disco:9292/Services/Client/Unauthenticated/MacSecureEnrol">http://disco:9292/Services/Client/Unauthenticated/MacSecureEnrol</a>
</div> </div>
<span class="smallText">This url will return a <a target="_blank" href="http://json.org/">JSON</a> response containing basic information about the enrolment.</span><br /> <span class="smallText">This url will return a <a target="_blank" href="http://json.org/">JSON</a> response containing basic information about the enrollment.</span><br />
<span class="smallMessage">This command makes use of <a target="_blank" href="http://curl.haxx.se/">cURL</a> (bundled with OSX). Other methods can also trigger a Mac Secure Enrol, <span class="smallMessage">
This command makes use of <a target="_blank" href="http://curl.haxx.se/">cURL</a> (bundled with OSX). Other methods can also trigger a Mac Secure Enroll,
such as an anchor (<span class="code">&lt;a&gt;</span>) or <span class="code">&lt;script&gt;</span> such as an anchor (<span class="code">&lt;a&gt;</span>) or <span class="code">&lt;script&gt;</span>
tag embedded on the organisation's intranet.</span> tag embedded on the organisation's intranet.
</span>
</td> </td>
</tr> </tr>
</table> </table>
</div> </div>
@if (canShowStatus && Authorization.Has(Claims.Config.Logging.Show)) @if (canShowStatus && Authorization.Has(Claims.Config.Logging.Show))
{ {
<h2>Live Enrolment Logging</h2> <h2>Live Enrollment Logging</h2>
@Html.Partial(MVC.Config.Shared.Views.LogEvents, new Disco.Web.Areas.Config.Models.Shared.LogEventsModel() @Html.Partial(MVC.Config.Shared.Views.LogEvents, new Disco.Web.Areas.Config.Models.Shared.LogEventsModel()
{ {
IsLive = true, IsLive = true,
@@ -160,6 +244,6 @@
} }
@if (canShowStatus) @if (canShowStatus)
{ {
@Html.ActionLinkButton("Enrolment Status", MVC.Config.Enrolment.Status()) @Html.ActionLinkButton("Enrollment Status", MVC.Config.Enrolment.Status())
} }
</div> </div>
@@ -51,7 +51,7 @@ namespace Disco.Web.Areas.Config.Views.Enrolment
var canConfig = Authorization.Has(Claims.Config.Enrolment.Configure); var canConfig = Authorization.Has(Claims.Config.Enrolment.Configure);
var canShowStatus = Authorization.Has(Claims.Config.Enrolment.ShowStatus); var canShowStatus = Authorization.Has(Claims.Config.Enrolment.ShowStatus);
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrolment"); ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrollment");
#line default #line default
@@ -62,60 +62,238 @@ WriteLiteral(" class=\"form\"");
WriteLiteral(" style=\"width: 530px;\""); WriteLiteral(" style=\"width: 530px;\"");
WriteLiteral(">\r\n <h2>Apple Mac Secure Enrol</h2>\r\n <table>\r\n <tr>\r\n <t" + WriteLiteral(">\r\n <table>\r\n <tr>\r\n <th>\r\n Pending Timeout:\r" +
"h>Username:\r\n </th>\r\n <td>"); "\n </th>\r\n <td>\r\n");
#line 16 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 17 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default
#line hidden
#line 17 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
if (canConfig) if (canConfig)
{ {
#line default
#line hidden
#line 18 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(Html.TextBoxFor(model => model.MacSshUsername));
#line default
#line hidden
#line 18 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 19 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 19 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(AjaxHelpers.AjaxSave()); Write(Html.TextBoxFor(model => model.PendingTimeoutMinutes, new { type = "number", min = "1" }));
#line default #line default
#line hidden #line hidden
#line 19 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 19 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default
#line hidden
#line 20 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(AjaxHelpers.AjaxSave());
#line default
#line hidden
#line 20 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default
#line hidden
#line 21 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(AjaxHelpers.AjaxLoader());
#line default
#line hidden
#line 21 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default
#line hidden
WriteLiteral(" <span> minutes <span");
WriteLiteral(" class=\"smallText\"");
WriteLiteral(">(default: 30)</span></span>\r\n");
WriteLiteral(" <script");
WriteLiteral(" type=\"text/javascript\"");
WriteLiteral(@">
$(function () {
var $DOM = $('#PendingTimeoutMinutes');
var $DOMAjaxSave = $DOM.next('.ajaxSave');
$DOM
.watermark('Minutes')
.focus(function () { $DOM.select() })
.keydown(function (e) {
$DOMAjaxSave.show();
if (e.which == 13) {
$(this).blur();
}
}).blur(function () {
$DOMAjaxSave.hide();
})
.change(function () {
$DOMAjaxSave.hide();
var $ajaxLoading = $DOMAjaxSave.next('.ajaxLoading').show();
var data = { PendingTimeoutMinutes: parseInt($DOM.val()) };
if (data.PendingTimeoutMinutes <= 0) {
alert('Pending Timeout must be greater than zero');
$ajaxLoading.hide();
return;
} else {
$.ajax({
url: '");
#line 48 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(Url.Action(MVC.API.Enrollment.PendingTimeoutMinutes()));
#line default
#line hidden
WriteLiteral(@"',
dataType: 'json',
method: 'POST',
data: data,
success: function (d) {
if (d == 'OK') {
$ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
} else {
$ajaxLoading.hide();
alert('Unable to update pending timeout: ' + d);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Unable to update pending timeout: ' + textStatus);
$ajaxLoading.hide();
}
});
}
});
});
</script>
");
#line 69 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
}
else
{
#line default
#line hidden
#line 72 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(TimeSpan.FromMinutes(Model.PendingTimeoutMinutes));
#line default
#line hidden
#line 72 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
}
#line default
#line hidden
WriteLiteral(" </td>\r\n </tr>\r\n <tr>\r\n <td");
WriteLiteral(" colspan=\"2\"");
WriteLiteral(">\r\n <span");
WriteLiteral(" class=\"smallText\"");
WriteLiteral(@">
If a device enrollment is not automatically approved it will remain pending until the timeout is reached.
Pending enrollments can be approved manually from the Enrollment Status page.
</span>
</td>
</tr>
</table>
</div>
<div");
WriteLiteral(" class=\"form\"");
WriteLiteral(" style=\"width: 530px; margin-top: 15px\"");
WriteLiteral(">\r\n <h2>Apple Mac Secure Enroll</h2>\r\n <table>\r\n <tr>\r\n <" +
"th>\r\n Username:\r\n </th>\r\n <td>\r\n");
#line 94 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 20 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 94 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(AjaxHelpers.AjaxLoader()); if (canConfig)
{
#line default
#line hidden
#line 96 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(Html.TextBoxFor(model => model.MacSshUsername));
#line default #line default
#line hidden #line hidden
#line 20 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 96 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default
#line hidden
#line 97 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(AjaxHelpers.AjaxSave());
#line default #line default
#line hidden #line hidden
WriteLiteral(" <script");
#line 97 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default
#line hidden
#line 98 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(AjaxHelpers.AjaxLoader());
#line default
#line hidden
#line 98 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default
#line hidden
WriteLiteral(" <script");
WriteLiteral(" type=\"text/javascript\""); WriteLiteral(" type=\"text/javascript\"");
@@ -142,7 +320,7 @@ WriteLiteral(@">
url: '"); url: '");
#line 41 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 119 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(Url.Action(MVC.API.Bootstrapper.MacSshUsername())); Write(Url.Action(MVC.API.Bootstrapper.MacSshUsername()));
@@ -166,11 +344,11 @@ WriteLiteral(@"',
}); });
}); });
}); });
</script> </script>
"); ");
#line 60 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 138 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
} }
else else
{ {
@@ -180,49 +358,55 @@ WriteLiteral(@"',
#line default #line default
#line hidden #line hidden
WriteLiteral(" <span"); WriteLiteral(" <span");
WriteLiteral(" class=\"smallMessage\""); WriteLiteral(" class=\"smallMessage\"");
WriteLiteral(">&lt;None Specified&gt;</span>\r\n"); WriteLiteral(">&lt;None Specified&gt;</span>\r\n");
#line 66 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 144 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
} }
else else
{ {
#line default #line default
#line hidden #line hidden
#line 69 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 147 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(Model.MacSshUsername); Write(Model.MacSshUsername);
#line default #line default
#line hidden #line hidden
#line 69 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 147 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
} }
} }
#line default #line default
#line hidden #line hidden
WriteLiteral(" </td>\r\n </tr>\r\n\r\n <tr>\r\n <th>Password:\r\n " + WriteLiteral(" </td>\r\n </tr>\r\n\r\n <tr>\r\n <th>\r\n " +
" </th>\r\n <td>"); " Password:\r\n </th>\r\n <td>\r\n");
#line 78 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 158 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default
#line hidden
#line 158 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
if (canConfig) if (canConfig)
{ {
#line default #line default
#line hidden #line hidden
WriteLiteral(" <input"); WriteLiteral(" <input");
WriteLiteral(" id=\"MacSshPassword\""); WriteLiteral(" id=\"MacSshPassword\"");
@@ -231,40 +415,40 @@ WriteLiteral(" type=\"password\"");
WriteLiteral(" />\r\n"); WriteLiteral(" />\r\n");
#line 81 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 161 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 81 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 161 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(AjaxHelpers.AjaxSave()); Write(AjaxHelpers.AjaxSave());
#line default #line default
#line hidden #line hidden
#line 81 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 161 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 82 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 162 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(AjaxHelpers.AjaxLoader()); Write(AjaxHelpers.AjaxLoader());
#line default #line default
#line hidden #line hidden
#line 82 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 162 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default #line default
#line hidden #line hidden
WriteLiteral(" <script"); WriteLiteral(" <script");
WriteLiteral(" type=\"text/javascript\""); WriteLiteral(" type=\"text/javascript\"");
@@ -291,7 +475,7 @@ WriteLiteral(@">
url: '"); url: '");
#line 103 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 183 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(Url.Action(MVC.API.Bootstrapper.MacSshPassword())); Write(Url.Action(MVC.API.Bootstrapper.MacSshPassword()));
@@ -315,11 +499,11 @@ WriteLiteral(@"',
}); });
}); });
}); });
</script> </script>
"); ");
#line 122 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 202 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
} }
else else
{ {
@@ -327,14 +511,14 @@ WriteLiteral(@"',
#line default #line default
#line hidden #line hidden
WriteLiteral(" "); WriteLiteral(" ");
WriteLiteral("********"); WriteLiteral("********");
WriteLiteral("\r\n"); WriteLiteral("\r\n");
#line 126 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 206 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
} }
@@ -348,14 +532,16 @@ WriteLiteral(">\r\n <span");
WriteLiteral(" class=\"smallText\""); WriteLiteral(" class=\"smallText\"");
WriteLiteral("><strong>Instructions:</strong> The above credentials must be\r\n " + WriteLiteral(">\r\n <strong>Instructions:</strong> The above credentials must " +
" able to connect to the requesting Apple Mac client via <a"); "be\r\n able to connect to the requesting Apple Mac client via <" +
"a");
WriteLiteral(" target=\"_blank\""); WriteLiteral(" target=\"_blank\"");
WriteLiteral(" href=\"http://en.wikipedia.org/wiki/Secure_Shell\""); WriteLiteral(" href=\"http://en.wikipedia.org/wiki/Secure_Shell\"");
WriteLiteral(">SSH</a>. Enter/Script the following command:</span>\r\n <div"); WriteLiteral(">SSH</a>. Enter/Script the following command:\r\n </span>\r\n " +
" <div");
WriteLiteral(" class=\"code\""); WriteLiteral(" class=\"code\"");
@@ -376,19 +562,19 @@ WriteLiteral(" target=\"_blank\"");
WriteLiteral(" href=\"http://json.org/\""); WriteLiteral(" href=\"http://json.org/\"");
WriteLiteral(">JSON</a> response containing basic information about the enrolment.</span><br />" + WriteLiteral(">JSON</a> response containing basic information about the enrollment.</span><br /" +
"\r\n <span"); ">\r\n <span");
WriteLiteral(" class=\"smallMessage\""); WriteLiteral(" class=\"smallMessage\"");
WriteLiteral(">This command makes use of <a"); WriteLiteral(">\r\n This command makes use of <a");
WriteLiteral(" target=\"_blank\""); WriteLiteral(" target=\"_blank\"");
WriteLiteral(" href=\"http://curl.haxx.se/\""); WriteLiteral(" href=\"http://curl.haxx.se/\"");
WriteLiteral(">cURL</a> (bundled with OSX). Other methods can also trigger a Mac Secure Enrol,\r" + WriteLiteral(">cURL</a> (bundled with OSX). Other methods can also trigger a Mac Secure Enroll," +
"\n such as an anchor (<span"); "\r\n such as an anchor (<span");
WriteLiteral(" class=\"code\""); WriteLiteral(" class=\"code\"");
@@ -397,26 +583,27 @@ WriteLiteral(">&lt;a&gt;</span>) or <span");
WriteLiteral(" class=\"code\""); WriteLiteral(" class=\"code\"");
WriteLiteral(">&lt;script&gt;</span>\r\n tag embedded on the organisation\'s in" + WriteLiteral(">&lt;script&gt;</span>\r\n tag embedded on the organisation\'s in" +
"tranet.</span>\r\n </td>\r\n </tr>\r\n </table>\r\n</div>\r\n"); "tranet.\r\n </span>\r\n </td>\r\n </tr>\r\n </table>" +
"\r\n</div>\r\n");
#line 144 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 228 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
if (canShowStatus && Authorization.Has(Claims.Config.Logging.Show)) if (canShowStatus && Authorization.Has(Claims.Config.Logging.Show))
{ {
#line default #line default
#line hidden #line hidden
WriteLiteral(" <h2>Live Enrolment Logging</h2>\r\n"); WriteLiteral(" <h2>Live Enrollment Logging</h2>\r\n");
#line 147 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 231 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 147 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 231 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(Html.Partial(MVC.Config.Shared.Views.LogEvents, new Disco.Web.Areas.Config.Models.Shared.LogEventsModel() Write(Html.Partial(MVC.Config.Shared.Views.LogEvents, new Disco.Web.Areas.Config.Models.Shared.LogEventsModel()
{ {
IsLive = true, IsLive = true,
@@ -430,7 +617,7 @@ Write(Html.Partial(MVC.Config.Shared.Views.LogEvents, new Disco.Web.Areas.Config
#line default #line default
#line hidden #line hidden
#line 154 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 238 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
} }
@@ -444,13 +631,13 @@ WriteLiteral(" class=\"actionBar\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 157 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 241 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 157 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 241 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
if (Authorization.Has(Claims.Config.Enrolment.DownloadBootstrapper)) if (Authorization.Has(Claims.Config.Enrolment.DownloadBootstrapper))
{ {
@@ -458,14 +645,14 @@ WriteLiteral(">\r\n");
#line default #line default
#line hidden #line hidden
#line 159 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 243 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(Html.ActionLinkButton("Download Bootstrapper", MVC.Services.Client.Bootstrapper())); Write(Html.ActionLinkButton("Download Bootstrapper", MVC.Services.Client.Bootstrapper()));
#line default #line default
#line hidden #line hidden
#line 159 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 243 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
} }
@@ -475,7 +662,7 @@ WriteLiteral(">\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 161 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 245 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
if (canShowStatus) if (canShowStatus)
{ {
@@ -483,15 +670,15 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 163 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 247 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
Write(Html.ActionLinkButton("Enrolment Status", MVC.Config.Enrolment.Status())); Write(Html.ActionLinkButton("Enrollment Status", MVC.Config.Enrolment.Status()));
#line default #line default
#line hidden #line hidden
#line 163 "..\..\Areas\Config\Views\Enrolment\Index.cshtml" #line 247 "..\..\Areas\Config\Views\Enrolment\Index.cshtml"
} }
@@ -1,27 +1,49 @@
@{ @{
Authorization.Require(Claims.Config.Enrolment.ShowStatus); Authorization.Require(Claims.Config.Enrolment.ShowStatus);
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrolment", MVC.Config.Enrolment.Index(), "Status"); ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrollment", MVC.Config.Enrolment.Index(), "Status");
Html.BundleDeferred("~/ClientScripts/Modules/Knockout"); Html.BundleDeferred("~/ClientScripts/Modules/Knockout");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR"); Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-Isotope"); Html.BundleDeferred("~/ClientScripts/Modules/jQuery-Isotope");
} }
<div id="enrolStatus"> <div id="enrolStatus">
<div id="noSessions" data-bind="visible: noSessions"> <div id="noSessions" data-bind="visible: noSessions">
<h2>No enrolment sessions today</h2> <h2>No enrollment sessions today</h2>
</div> </div>
<div id="sessions" data-bind="visible: !noSessions(), foreach: { data: sessions, afterRender: sessionRendered, afterAdd: sessionAdded }" style="display: none"> <div id="sessions" data-bind="visible: !noSessions(), foreach: { data: sessions, afterRender: sessionRendered, afterAdd: sessionAdded }" style="display: none">
<div class="session" data-bind="style: { backgroundImage: deviceModelImageUrl }, click: select"> <div class="session" data-bind="style: { backgroundImage: deviceModelImageUrl }, click: select">
<h3> <h3>
<span data-bind="text: title"></span> <span data-bind="text: title"></span>
<span class="details" data-bind="text: '(' + deviceModelDescription() + ')'"></span> <span class="details" data-bind="text: '(' + deviceModelDescription() + ')'"></span>
<span class="pending" data-bind="visible: isPending"><code data-bind="text: pendingIdentifier"></code> <i class="fa fa-exclamation-circle"></i></span>
</h3> </h3>
<p class="sessionStart" data-bind="text: startTime"></p> <p class="sessionStart" data-bind="text: startTime"></p>
<p class="sessionStatus" data-bind="text: progressStatus"></p> <p class="sessionStatus" data-bind="text: progressStatus"></p>
<div data-bind="visible: !sessionEnded(), progressValue: progressValue" class="sessionProgress"></div> <div data-bind="visible: !sessionEnded() && progressValue >= 0, progressValue: progressValue" class="sessionProgress"></div>
</div> </div>
</div> </div>
<div id="dialogSession" data-bind="with: currentSession"> <div id="dialogSession" data-bind="with: currentSession">
<div class="sessionProgress clearfix">
<p class="sessionStart" data-bind="text: startTime"></p>
<p class="sessionStatus" data-bind="text: progressStatus"></p>
<div data-bind="visible: !sessionEnded() && progressValue >= 0, progressValue: progressValue"></div>
<div id="formResolveSessionPending" data-bind="visible: isPending">
@using (Html.BeginForm(MVC.API.Enrollment.ResolveSessionPending(), FormMethod.Post))
{
<code data-bind="text: pendingIdentifier"></code>
@Html.AntiForgeryToken();
<input type="hidden" name="sessionId" data-bind="value: id" />
<div class="reason">
<input type="text" name="reason" placeholder="Reason (optional)" />
</div>
<div class="buttons">
<button type="button" value="True" class="button">Approve</button>
<button type="button" value="False" class="button">Reject</button>
</div>
}
</div>
</div>
<div class="sessionHeader clearfix" data-bind="style: { backgroundImage: deviceModelImageUrl }"> <div class="sessionHeader clearfix" data-bind="style: { backgroundImage: deviceModelImageUrl }">
<h2><a href="" target="_blank" data-bind="text: title, attr: { href: deviceUrl }"></a></h2> <h2><a href="" target="_blank" data-bind="text: title, attr: { href: deviceUrl }"></a></h2>
<h3 data-bind="text: deviceModelDescription"></h3> <h3 data-bind="text: deviceModelDescription"></h3>
@@ -48,11 +70,6 @@
</tr> </tr>
</table> </table>
</div> </div>
<div class="sessionProgress clearfix">
<p class="sessionStart" data-bind="text: startTime"></p>
<p class="sessionStatus" data-bind="text: progressStatus"></p>
<div data-bind="visible: !sessionEnded(), progressValue: progressValue"></div>
</div>
<div class="sessionInfoContainer clearfix"> <div class="sessionInfoContainer clearfix">
<div class="sessionInfoMessages"> <div class="sessionInfoMessages">
<table class="logEventsViewport"> <table class="logEventsViewport">
@@ -134,7 +151,10 @@
function sessionViewModel(id) { function sessionViewModel(id) {
var self = this; var self = this;
self.id = id;
self.title = ko.observable(id); self.title = ko.observable(id);
self.isPending = ko.observable(false);
self.pendingIdentifier = ko.observable();
self.messages = ko.observableArray(); self.messages = ko.observableArray();
self.console = ko.observableArray(); self.console = ko.observableArray();
self.serialNumber = ko.observable(); self.serialNumber = ko.observable();
@@ -187,7 +207,7 @@
self.select = function (e, d) { self.select = function (e, d) {
vm.currentSession(self); vm.currentSession(self);
hostDialogSessions.dialog('open'); hostDialogSessions.dialog('open');
hostDialogSessions.dialog('option', 'title', 'Device Enrolment: ' + self.title()); hostDialogSessions.dialog('option', 'title', 'Device Enrollment: ' + self.title());
} }
} }
@@ -228,15 +248,39 @@
if (log.Arguments.length >= 10 && log.Arguments[9]) if (log.Arguments.length >= 10 && log.Arguments[9])
session.deviceModelId(log.Arguments[9]); session.deviceModelId(log.Arguments[9]);
break; break;
case 14: // SessionPending
session.isPending(true);
session.pendingIdentifier(log.Arguments[4]);
session.messages.unshift(log);
session.progressValue(-1);
session.progressStatus('Pending enrollment approval');
break;
case 15: // SessionPendingApproved
session.isPending(false);
session.messages.unshift(log);
session.progressValue(-1);
session.progressStatus('Enrollment approval, waiting for client');
break;
case 16: // SessionPendingRejected
session.isPending(false);
session.messages.unshift(log);
session.progressValue(-1);
session.progressStatus('Enrollment rejected, waiting for client');
break;
case 17: // SessionContinuing
session.isPending(false);
session.messages.unshift(log);
break;
case 20: // SessionFinished case 20: // SessionFinished
session.sessionEnded(true); session.sessionEnded(true);
session.isPending(false);
if (session.hasError()) if (session.hasError())
session.progressStatus('Enrolment Finished with an Error'); session.progressStatus('Enrollment Finished with an Error');
else else
if (session.hasWarning()) if (session.hasWarning())
session.progressStatus('Enrolment Finished with a Warning'); session.progressStatus('Enrollment Finished with a Warning');
else else
session.progressStatus('Enrolment Finished Successfully'); session.progressStatus('Enrollment Finished Successfully');
session.messages.unshift(log); session.messages.unshift(log);
break; break;
case 21: // SessionDiagnosticInformation case 21: // SessionDiagnosticInformation
@@ -357,6 +401,20 @@
} }
} }
} }
$('#dialogSession').on('click', '#formResolveSessionPending button', function (e) {
const $button = $(this);
const $form = $button.closest('form');
const body = new FormData($form[0]);
body.append('approve', $button.val());
fetch($form.attr('action'), {
method: 'POST',
body: body
}).then(function (response) {
if (!response.ok) {
alert('Failed to resolve pending session: ' + response.statusText);
}
});
});
init(); init();
}); });
</script> </script>
@@ -48,7 +48,7 @@ namespace Disco.Web.Areas.Config.Views.Enrolment
Authorization.Require(Claims.Config.Enrolment.ShowStatus); Authorization.Require(Claims.Config.Enrolment.ShowStatus);
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrolment", MVC.Config.Enrolment.Index(), "Status"); ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Enrollment", MVC.Config.Enrolment.Index(), "Status");
Html.BundleDeferred("~/ClientScripts/Modules/Knockout"); Html.BundleDeferred("~/ClientScripts/Modules/Knockout");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR"); Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-Isotope"); Html.BundleDeferred("~/ClientScripts/Modules/jQuery-Isotope");
@@ -66,7 +66,7 @@ WriteLiteral(" id=\"noSessions\"");
WriteLiteral(" data-bind=\"visible: noSessions\""); WriteLiteral(" data-bind=\"visible: noSessions\"");
WriteLiteral(">\r\n <h2>No enrolment sessions today</h2>\r\n </div>\r\n <div"); WriteLiteral(">\r\n <h2>No enrollment sessions today</h2>\r\n </div>\r\n <div");
WriteLiteral(" id=\"sessions\""); WriteLiteral(" id=\"sessions\"");
@@ -91,7 +91,21 @@ WriteLiteral(" class=\"details\"");
WriteLiteral(" data-bind=\"text: \'(\' + deviceModelDescription() + \')\'\""); WriteLiteral(" data-bind=\"text: \'(\' + deviceModelDescription() + \')\'\"");
WriteLiteral("></span>\r\n </h3>\r\n <p"); WriteLiteral("></span>\r\n <span");
WriteLiteral(" class=\"pending\"");
WriteLiteral(" data-bind=\"visible: isPending\"");
WriteLiteral("><code");
WriteLiteral(" data-bind=\"text: pendingIdentifier\"");
WriteLiteral("></code> <i");
WriteLiteral(" class=\"fa fa-exclamation-circle\"");
WriteLiteral("></i></span>\r\n \r\n </h3>\r\n <p");
WriteLiteral(" class=\"sessionStart\""); WriteLiteral(" class=\"sessionStart\"");
@@ -105,7 +119,8 @@ WriteLiteral(" data-bind=\"text: progressStatus\"");
WriteLiteral("></p>\r\n <div"); WriteLiteral("></p>\r\n <div");
WriteLiteral(" data-bind=\"visible: !sessionEnded(), progressValue: progressValue\""); WriteLiteral(" data-bind=\"visible: !sessionEnded() && progressValue >= 0, progressValue: progre" +
"ssValue\"");
WriteLiteral(" class=\"sessionProgress\""); WriteLiteral(" class=\"sessionProgress\"");
@@ -117,6 +132,128 @@ WriteLiteral(" data-bind=\"with: currentSession\"");
WriteLiteral(">\r\n <div"); WriteLiteral(">\r\n <div");
WriteLiteral(" class=\"sessionProgress clearfix\"");
WriteLiteral(">\r\n <p");
WriteLiteral(" class=\"sessionStart\"");
WriteLiteral(" data-bind=\"text: startTime\"");
WriteLiteral("></p>\r\n <p");
WriteLiteral(" class=\"sessionStatus\"");
WriteLiteral(" data-bind=\"text: progressStatus\"");
WriteLiteral("></p>\r\n <div");
WriteLiteral(" data-bind=\"visible: !sessionEnded() && progressValue >= 0, progressValue: progre" +
"ssValue\"");
WriteLiteral("></div>\r\n <div");
WriteLiteral(" id=\"formResolveSessionPending\"");
WriteLiteral(" data-bind=\"visible: isPending\"");
WriteLiteral(">\r\n");
#line 32 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
#line default
#line hidden
#line 32 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
using (Html.BeginForm(MVC.API.Enrollment.ResolveSessionPending(), FormMethod.Post))
{
#line default
#line hidden
WriteLiteral(" <code");
WriteLiteral(" data-bind=\"text: pendingIdentifier\"");
WriteLiteral("></code>\r\n");
#line 35 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
#line default
#line hidden
#line 35 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
Write(Html.AntiForgeryToken());
#line default
#line hidden
#line 35 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
;
#line default
#line hidden
WriteLiteral(" <input");
WriteLiteral(" type=\"hidden\"");
WriteLiteral(" name=\"sessionId\"");
WriteLiteral(" data-bind=\"value: id\"");
WriteLiteral(" />\r\n");
WriteLiteral(" <div");
WriteLiteral(" class=\"reason\"");
WriteLiteral(">\r\n <input");
WriteLiteral(" type=\"text\"");
WriteLiteral(" name=\"reason\"");
WriteLiteral(" placeholder=\"Reason (optional)\"");
WriteLiteral(" />\r\n </div>\r\n");
WriteLiteral(" <div");
WriteLiteral(" class=\"buttons\"");
WriteLiteral(">\r\n <button");
WriteLiteral(" type=\"button\"");
WriteLiteral(" value=\"True\"");
WriteLiteral(" class=\"button\"");
WriteLiteral(">Approve</button>\r\n <button");
WriteLiteral(" type=\"button\"");
WriteLiteral(" value=\"False\"");
WriteLiteral(" class=\"button\"");
WriteLiteral(">Reject</button>\r\n </div>\r\n");
#line 44 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
}
#line default
#line hidden
WriteLiteral(" </div>\r\n </div>\r\n <div");
WriteLiteral(" class=\"sessionHeader clearfix\""); WriteLiteral(" class=\"sessionHeader clearfix\"");
WriteLiteral(" data-bind=\"style: { backgroundImage: deviceModelImageUrl }\""); WriteLiteral(" data-bind=\"style: { backgroundImage: deviceModelImageUrl }\"");
@@ -181,26 +318,6 @@ WriteLiteral(" data-bind=\"text: sessionDeviceInfo().Arguments[6] + \' \' + sess
WriteLiteral("></td>\r\n </tr>\r\n </table>\r\n </div>\r\n <div" + WriteLiteral("></td>\r\n </tr>\r\n </table>\r\n </div>\r\n <div" +
""); "");
WriteLiteral(" class=\"sessionProgress clearfix\"");
WriteLiteral(">\r\n <p");
WriteLiteral(" class=\"sessionStart\"");
WriteLiteral(" data-bind=\"text: startTime\"");
WriteLiteral("></p>\r\n <p");
WriteLiteral(" class=\"sessionStatus\"");
WriteLiteral(" data-bind=\"text: progressStatus\"");
WriteLiteral("></p>\r\n <div");
WriteLiteral(" data-bind=\"visible: !sessionEnded(), progressValue: progressValue\"");
WriteLiteral("></div>\r\n </div>\r\n <div");
WriteLiteral(" class=\"sessionInfoContainer clearfix\""); WriteLiteral(" class=\"sessionInfoContainer clearfix\"");
WriteLiteral(">\r\n <div"); WriteLiteral(">\r\n <div");
@@ -309,7 +426,7 @@ WriteLiteral(@">
var deviceBaseUrl = '"); var deviceBaseUrl = '");
#line 107 "..\..\Areas\Config\Views\Enrolment\Status.cshtml" #line 124 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
Write(Url.Action(MVC.Device.Show())); Write(Url.Action(MVC.Device.Show()));
@@ -318,7 +435,7 @@ WriteLiteral(@">
WriteLiteral("/\'\r\n var deviceModelImageUrl = \'"); WriteLiteral("/\'\r\n var deviceModelImageUrl = \'");
#line 108 "..\..\Areas\Config\Views\Enrolment\Status.cshtml" #line 125 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
Write(Url.Action(MVC.API.DeviceModel.Image())); Write(Url.Action(MVC.API.DeviceModel.Image()));
@@ -327,7 +444,7 @@ WriteLiteral("/\'\r\n var deviceModelImageUrl = \'");
WriteLiteral("/\'\r\n var iconWarningUrl = \'url("); WriteLiteral("/\'\r\n var iconWarningUrl = \'url(");
#line 109 "..\..\Areas\Config\Views\Enrolment\Status.cshtml" #line 126 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
Write(Links.ClientSource.Style.Images.Status.warning32_png); Write(Links.ClientSource.Style.Images.Status.warning32_png);
@@ -336,7 +453,7 @@ WriteLiteral("/\'\r\n var iconWarningUrl = \'url(");
WriteLiteral(")\';\r\n var iconErrorUrl = \'url("); WriteLiteral(")\';\r\n var iconErrorUrl = \'url(");
#line 110 "..\..\Areas\Config\Views\Enrolment\Status.cshtml" #line 127 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
Write(Links.ClientSource.Style.Images.Status.fail32_png); Write(Links.ClientSource.Style.Images.Status.fail32_png);
@@ -352,94 +469,114 @@ WriteLiteral(")\';\r\n\r\n function pageViewModel() {\r\n var
"nction (e, d) {\r\n if (self.isotopeInited) {\r\n " + "nction (e, d) {\r\n if (self.isotopeInited) {\r\n " +
"hostSessions.isotope(\'reloadItems\').isotope({ sortBy: \'original-order\' });\r\n " + "hostSessions.isotope(\'reloadItems\').isotope({ sortBy: \'original-order\' });\r\n " +
" }\r\n };\r\n }\r\n function sessionViewModel(id) " + " }\r\n };\r\n }\r\n function sessionViewModel(id) " +
"{\r\n var self = this;\r\n\r\n self.title = ko.observable(id);\r\n" + "{\r\n var self = this;\r\n\r\n self.id = id;\r\n self.t" +
" self.messages = ko.observableArray();\r\n self.console = ko" + "itle = ko.observable(id);\r\n self.isPending = ko.observable(false);\r\n " +
".observableArray();\r\n self.serialNumber = ko.observable();\r\n " + " self.pendingIdentifier = ko.observable();\r\n self.messages " +
" self.sessionDeviceInfo = ko.observable();\r\n self.progressStatus = " + "= ko.observableArray();\r\n self.console = ko.observableArray();\r\n " +
"ko.observable();\r\n self.progressValue = ko.observable();\r\n " + " self.serialNumber = ko.observable();\r\n self.sessionDeviceInfo " +
" self.startTime = ko.observable();\r\n self.sessionEnded = ko.observabl" + "= ko.observable();\r\n self.progressStatus = ko.observable();\r\n " +
"e(false);\r\n self.progressbar = null;\r\n self.hasError = ko." + " self.progressValue = ko.observable();\r\n self.startTime = ko.obser" +
"observable(false);\r\n self.hasWarning = ko.observable(false);\r\n " + "vable();\r\n self.sessionEnded = ko.observable(false);\r\n sel" +
" self.deviceModelId = ko.observable();\r\n self.deviceModelDescript" + "f.progressbar = null;\r\n self.hasError = ko.observable(false);\r\n " +
"ion = ko.computed(function () {\r\n var deviceModelId = self.device" + " self.hasWarning = ko.observable(false);\r\n self.deviceModelId = " +
"ModelId();\r\n var sessionDeviceInfo = self.sessionDeviceInfo();\r\n " + "ko.observable();\r\n self.deviceModelDescription = ko.computed(function" +
" if (deviceModelId) {\r\n var dm = deviceModels[d" + " () {\r\n var deviceModelId = self.deviceModelId();\r\n " +
"eviceModelId];\r\n if (dm) {\r\n if (dm.De" + " var sessionDeviceInfo = self.sessionDeviceInfo();\r\n if (deviceM" +
"scription)\r\n return dm.Description;\r\n " + "odelId) {\r\n var dm = deviceModels[deviceModelId];\r\n " +
" else\r\n return dm.Manufacturer + \' \' + dm.Mode" + " if (dm) {\r\n if (dm.Description)\r\n " +
"l;\r\n }\r\n }\r\n if (sessionDeviceI" + " return dm.Description;\r\n else\r\n " +
"nfo) {\r\n return sessionDeviceInfo.Arguments[6] + \' \' + sessio" + " return dm.Manufacturer + \' \' + dm.Model;\r\n }\r" +
"nDeviceInfo.Arguments[7];\r\n }\r\n });\r\n self." + "\n }\r\n if (sessionDeviceInfo) {\r\n " +
"deviceUrl = ko.computed(function () {\r\n var serialNumber = self.s" + " return sessionDeviceInfo.Arguments[6] + \' \' + sessionDeviceInfo.Arguments[7];\r" +
"erialNumber();\r\n if (serialNumber)\r\n return de" + "\n }\r\n });\r\n self.deviceUrl = ko.computed(fu" +
"viceBaseUrl + serialNumber;\r\n else\r\n return nu" + "nction () {\r\n var serialNumber = self.serialNumber();\r\n " +
"ll;\r\n });\r\n self.deviceModelImageUrl = ko.computed(functio" + " if (serialNumber)\r\n return deviceBaseUrl + serialNumber" +
"n () {\r\n var deviceModelImage;\r\n if (self.deviceMo" + ";\r\n else\r\n return null;\r\n });\r\n " +
"delId())\r\n deviceModelImage = \'url(\' + deviceModelImageUrl + " + " self.deviceModelImageUrl = ko.computed(function () {\r\n va" +
"self.deviceModelId() + \')\';\r\n else\r\n deviceMod" + "r deviceModelImage;\r\n if (self.deviceModelId())\r\n " +
"elImage = \'url(\' + deviceModelImageUrl + \')\';\r\n if (self.hasError" + " deviceModelImage = \'url(\' + deviceModelImageUrl + self.deviceModelId() + \')\'" +
"())\r\n return iconErrorUrl + \', \' + deviceModelImage;\r\n " + ";\r\n else\r\n deviceModelImage = \'url(\' + deviceM" +
" else\r\n if (self.hasWarning())\r\n " + "odelImageUrl + \')\';\r\n if (self.hasError())\r\n r" +
" return iconWarningUrl + \', \' + deviceModelImage;\r\n else\r\n " + "eturn iconErrorUrl + \', \' + deviceModelImage;\r\n else\r\n " +
" return \'none, \' + deviceModelImage;\r\n });\r\n " + " if (self.hasWarning())\r\n return iconWarningUrl +" +
" self.select = function (e, d) {\r\n vm.currentSession(self" + " \', \' + deviceModelImage;\r\n else\r\n ret" +
");\r\n hostDialogSessions.dialog(\'open\');\r\n hostDial" + "urn \'none, \' + deviceModelImage;\r\n });\r\n self.select = fun" +
"ogSessions.dialog(\'option\', \'title\', \'Device Enrolment: \' + self.title());\r\n " + "ction (e, d) {\r\n vm.currentSession(self);\r\n hostDi" +
" }\r\n }\r\n\r\n function parseLog(log) {\r\n if (log.Mo" + "alogSessions.dialog(\'open\');\r\n hostDialogSessions.dialog(\'option\'" +
"duleId === 50 && log.Arguments && log.Arguments.length > 0) {\r\n /" + ", \'title\', \'Device Enrollment: \' + self.title());\r\n }\r\n }\r\n\r\n " +
"/ find session\r\n var sessionId = log.Arguments[0];\r\n " + " function parseLog(log) {\r\n if (log.ModuleId === 50 && log.Argu" +
" var session = vm.sessionIndex[sessionId];\r\n if (!session && lo" + "ments && log.Arguments.length > 0) {\r\n // find session\r\n " +
"g.EventTypeId === 10) { // Starting Session (Ignore \'partial\' sessions)\r\n " + " var sessionId = log.Arguments[0];\r\n var session = vm.sessi" +
" session = new sessionViewModel(sessionId);\r\n vm." + "onIndex[sessionId];\r\n if (!session && log.EventTypeId === 10) { /" +
"sessionIndex[sessionId] = session;\r\n vm.sessions.unshift(sess" + "/ Starting Session (Ignore \'partial\' sessions)\r\n session = ne" +
"ion);\r\n vm.noSessions(false);\r\n }\r\n " + "w sessionViewModel(sessionId);\r\n vm.sessionIndex[sessionId] =" +
" if (session) {\r\n switch (log.EventTypeId) {\r\n " + " session;\r\n vm.sessions.unshift(session);\r\n " +
" case 10: // SessionStarting\r\n session.ti" + " vm.noSessions(false);\r\n }\r\n if (session) {\r\n " +
"tle(log.Arguments[1]);\r\n session.startTime(log.Format" + " switch (log.EventTypeId) {\r\n case 10: // " +
"tedTimestamp.substring(log.FormattedTimestamp.indexOf(\' \') + 1));\r\n " + "SessionStarting\r\n session.title(log.Arguments[1]);\r\n " +
" session.messages.unshift(log);\r\n break" + " session.startTime(log.FormattedTimestamp.substring(lo" +
";\r\n case 11: // SessionProgress\r\n " + "g.FormattedTimestamp.indexOf(\' \') + 1));\r\n session.me" +
" //session.progressbar.progressbar(\'option\', \'value\', log.Arguments[1]);\r\n " +
" session.progressValue(log.Arguments[1]);\r\n " +
" session.progressStatus(log.Arguments[2]);\r\n " +
" break;\r\n case 12: // SessionDevice\r\n " +
" session.title(log.Arguments[1]);\r\n sessi" +
"on.serialNumber(log.Arguments[1]);\r\n if (log.Argument" +
"s.length >= 3 && log.Arguments[2])\r\n session.devi" +
"ceModelId(log.Arguments[2]);\r\n break;\r\n " +
" break;\r\n case 13: // SessionDeviceInfo\r\n " +
" session.title(log.Arguments[1]);\r\n " +
" session.serialNumber(log.Arguments[1]);\r\n sess" +
"ion.sessionDeviceInfo(log);\r\n if (log.Arguments.lengt" +
"h >= 10 && log.Arguments[9])\r\n session.deviceMode" +
"lId(log.Arguments[9]);\r\n break;\r\n " +
" case 20: // SessionFinished\r\n session.sessionEnde" +
"d(true);\r\n if (session.hasError())\r\n " +
" session.progressStatus(\'Enrolment Finished with an Error\');\r\n " +
" else\r\n if (session.hasWar" +
"ning())\r\n session.progressStatus(\'Enrolment F" +
"inished with a Warning\');\r\n else\r\n " +
" session.progressStatus(\'Enrolment Finished Successfully\');\r" +
"\n session.messages.unshift(log);\r\n " +
" break;\r\n case 21: // SessionDiagnosticInformatio" +
"n\r\n session.console.push(log);\r\n " +
" break;\r\n case 22: // SessionWarning\r\n " +
" session.hasWarning(true);\r\n session.me" +
"ssages.unshift(log);\r\n break;\r\n " + "ssages.unshift(log);\r\n break;\r\n " +
" case 23: // SessionError\r\n case 24: // SessionErrorWith" + " case 11: // SessionProgress\r\n //session.progressbar" +
"Inner\r\n case 25: // SessionClientError\r\n " + ".progressbar(\'option\', \'value\', log.Arguments[1]);\r\n " +
" session.hasError(true);\r\n session.messages" + "session.progressValue(log.Arguments[1]);\r\n session.pr" +
".unshift(log);\r\n break;\r\n defa" + "ogressStatus(log.Arguments[2]);\r\n break;\r\n " +
"ult:\r\n session.messages.unshift(log);\r\n " + " case 12: // SessionDevice\r\n session.titl" +
" }\r\n }\r\n }\r\n }\r\n function init() {\r" + "e(log.Arguments[1]);\r\n session.serialNumber(log.Argum" +
"\n hostDialogSessions.dialog({\r\n modal: true,\r\n " + "ents[1]);\r\n if (log.Arguments.length >= 3 && log.Argu" +
" height: 574,\r\n width: 900,\r\n resizable: fa" + "ments[2])\r\n session.deviceModelId(log.Arguments[2" +
"lse,\r\n autoOpen: false\r\n });\r\n //hostDialog" + "]);\r\n break;\r\n break;\r\n " +
"SessionsProgress.progressbar();\r\n\r\n // Create View Model\r\n " + " case 13: // SessionDeviceInfo\r\n " +
" vm = new pageViewModel();\r\n $.ajax({\r\n url: \'"); "session.title(log.Arguments[1]);\r\n session.serialNumb" +
"er(log.Arguments[1]);\r\n session.sessionDeviceInfo(log" +
");\r\n if (log.Arguments.length >= 10 && log.Arguments[" +
"9])\r\n session.deviceModelId(log.Arguments[9]);\r\n " +
" break;\r\n case 14: // SessionPe" +
"nding\r\n session.isPending(true);\r\n " +
" session.pendingIdentifier(log.Arguments[4]);\r\n " +
" session.messages.unshift(log);\r\n session.progressV" +
"alue(-1);\r\n session.progressStatus(\'Pending enrollmen" +
"t approval\');\r\n break;\r\n case " +
"15: // SessionPendingApproved\r\n session.isPending(fal" +
"se);\r\n session.messages.unshift(log);\r\n " +
" session.progressValue(-1);\r\n session.pr" +
"ogressStatus(\'Enrollment approval, waiting for client\');\r\n " +
" break;\r\n case 16: // SessionPendingRejected\r\n " +
" session.isPending(false);\r\n ses" +
"sion.messages.unshift(log);\r\n session.progressValue(-" +
"1);\r\n session.progressStatus(\'Enrollment rejected, wa" +
"iting for client\');\r\n break;\r\n " +
" case 17: // SessionContinuing\r\n session.isPending(fa" +
"lse);\r\n session.messages.unshift(log);\r\n " +
" break;\r\n case 20: // SessionFinished\r\n " +
" session.sessionEnded(true);\r\n " +
" session.isPending(false);\r\n if (session.hasError())\r" +
"\n session.progressStatus(\'Enrollment Finished wit" +
"h an Error\');\r\n else\r\n " +
" if (session.hasWarning())\r\n session.progress" +
"Status(\'Enrollment Finished with a Warning\');\r\n e" +
"lse\r\n session.progressStatus(\'Enrollment Fini" +
"shed Successfully\');\r\n session.messages.unshift(log);" +
"\r\n break;\r\n case 21: // Sessio" +
"nDiagnosticInformation\r\n session.console.push(log);\r\n" +
" break;\r\n case 22: // SessionW" +
"arning\r\n session.hasWarning(true);\r\n " +
" session.messages.unshift(log);\r\n break;\r\n " +
" case 23: // SessionError\r\n case 24" +
": // SessionErrorWithInner\r\n case 25: // SessionClientErr" +
"or\r\n session.hasError(true);\r\n " +
" session.messages.unshift(log);\r\n break;\r\n " +
" default:\r\n session.messages.unshift(" +
"log);\r\n }\r\n }\r\n }\r\n }\r\n " +
" function init() {\r\n hostDialogSessions.dialog({\r\n m" +
"odal: true,\r\n height: 574,\r\n width: 900,\r\n " +
" resizable: false,\r\n autoOpen: false\r\n });\r\n " +
" //hostDialogSessionsProgress.progressbar();\r\n\r\n // Create Vi" +
"ew Model\r\n vm = new pageViewModel();\r\n $.ajax({\r\n " +
" url: \'");
#line 274 "..\..\Areas\Config\Views\Enrolment\Status.cshtml" #line 318 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
Write(Url.Action(MVC.API.DeviceModel.Index())); Write(Url.Action(MVC.API.DeviceModel.Index()));
@@ -473,7 +610,7 @@ WriteLiteral(@"',
url: '"); url: '");
#line 299 "..\..\Areas\Config\Views\Enrolment\Status.cshtml" #line 343 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
Write(Url.Action(MVC.API.Logging.RetrieveEvents())); Write(Url.Action(MVC.API.Logging.RetrieveEvents()));
@@ -512,7 +649,7 @@ WriteLiteral(@"',
$.connection.hub.qs = { LogModules: '"); $.connection.hub.qs = { LogModules: '");
#line 329 "..\..\Areas\Config\Views\Enrolment\Status.cshtml" #line 373 "..\..\Areas\Config\Views\Enrolment\Status.cshtml"
Write(Disco.Services.Devices.Enrolment.EnrolmentLog.Current.LiveLogGroupName); Write(Disco.Services.Devices.Enrolment.EnrolmentLog.Current.LiveLogGroupName);
@@ -537,7 +674,15 @@ WriteLiteral("\' };\r\n $.connection.hub.error(onHubFailed);\r\n\r\n
" \'Close\': function () {\r\n " + " \'Close\': function () {\r\n " +
" $(this).dialog(\'destroy\');\r\n }\r\n " + " $(this).dialog(\'destroy\');\r\n }\r\n " +
" }\r\n });\r\n }\r\n }" + " }\r\n });\r\n }\r\n }" +
"\r\n }\r\n init();\r\n });\r\n</script>\r\n"); "\r\n }\r\n $(\'#dialogSession\').on(\'click\', \'#formResolveSessionPending" +
" button\', function (e) {\r\n const $button = $(this);\r\n cons" +
"t $form = $button.closest(\'form\');\r\n const body = new FormData($form[" +
"0]);\r\n body.append(\'approve\', $button.val());\r\n fetch($for" +
"m.attr(\'action\'), {\r\n method: \'POST\',\r\n body: body" +
"\r\n }).then(function (response) {\r\n if (!response.ok) {" +
"\r\n alert(\'Failed to resolve pending session: \' + response.sta" +
"tusText);\r\n }\r\n });\r\n });\r\n init();\r\n " +
" });\r\n</script>\r\n");
} }
} }
@@ -75,6 +75,74 @@
</div> </div>
</td> </td>
</tr> </tr>
<tr>
<th style="width: 200px">On Device Ready For Return:</th>
<td>
@if (canConfig)
{
@Html.EditorFor(model => model.OnDeviceReadyForReturnExpression)
@AjaxHelpers.AjaxRemove()
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
var field = $('#OnDeviceReadyForReturnExpression');
var fieldRemove = field.next('.ajaxRemove');
var fieldOriginalWidth, fieldOriginalHeight;
document.DiscoFunctions.PropertyChangeHelper(
field,
'None',
'@Url.Action(MVC.API.JobPreferences.UpdateOnDeviceReadyForReturnExpression())',
'OnDeviceReadyForReturnExpression'
);
field.focus(function () {
fieldOriginalWidth = field.width();
fieldOriginalHeight = field.height();
field.css('overflow', 'visible').animate({ width: field.parent().width() - 42, height: 75 }, 200);
}).blur(function () {
field.css('overflow', 'hidden').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200);
}).change(function () {
if (!!field.val()) {
fieldRemove.show();
} else {
fieldRemove.hide();
}
}).attr('placeholder', 'None').attr('spellcheck', 'false');
fieldRemove.click(function () {
field.val('').change();
});
if (!!field.val()) {
fieldRemove.show();
} else {
fieldRemove.hide();
}
});
</script>
}
else
{
if (string.IsNullOrWhiteSpace(Model.OnDeviceReadyForReturnExpression))
{
<span class="smallMessage">&lt;None Specified&gt;</span>
}
else
{
<div class="code">
@Model.OnDeviceReadyForReturnExpression
</div>
}
}
<div class="info-box">
<p class="fa-p">
<i class="fa fa-fw fa-info-circle"></i>This expression will be evaluated whenever a device is flagged as Ready For Return. If the expression has any output it will be added to the job log.
</p>
</div>
</td>
</tr>
<tr> <tr>
<th style="width: 200px">On Close:</th> <th style="width: 200px">On Close:</th>
<td> <td>
@@ -250,7 +250,7 @@ WriteLiteral("></i>This expression will be evaluated whenever a job is created.
WriteLiteral(" style=\"width: 200px\""); WriteLiteral(" style=\"width: 200px\"");
WriteLiteral(">On Close:</th>\r\n <td>\r\n"); WriteLiteral(">On Device Ready For Return:</th>\r\n <td>\r\n");
#line 81 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml" #line 81 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
@@ -268,14 +268,14 @@ WriteLiteral(">On Close:</th>\r\n <td>\r\n");
#line hidden #line hidden
#line 83 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml" #line 83 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
Write(Html.EditorFor(model => model.OnCloseExpression)); Write(Html.EditorFor(model => model.OnDeviceReadyForReturnExpression));
#line default #line default
#line hidden #line hidden
#line 83 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml" #line 83 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
#line default #line default
@@ -327,50 +327,60 @@ WriteLiteral(" <script");
WriteLiteral(" type=\"text/javascript\""); WriteLiteral(" type=\"text/javascript\"");
WriteLiteral(@"> WriteLiteral(@">
$(function () { $(function () {
var field = $('#OnCloseExpression'); var field = $('#OnDeviceReadyForReturnExpression');
var fieldRemove = field.next('.ajaxRemove'); var fieldRemove = field.next('.ajaxRemove');
var fieldOriginalWidth, fieldOriginalHeight; var fieldOriginalWidth, fieldOriginalHeight;
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
field, field,
'None', 'None',
'"); '");
#line 96 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml" #line 96 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
Write(Url.Action(MVC.API.JobPreferences.UpdateOnCloseExpression())); Write(Url.Action(MVC.API.JobPreferences.UpdateOnDeviceReadyForReturnExpression()));
#line default #line default
#line hidden #line hidden
WriteLiteral("\',\r\n \'OnCloseExpression\'\r\n " + WriteLiteral(@"',
" );\r\n\r\n field.focus(function () {\r\n " + 'OnDeviceReadyForReturnExpression'
" fieldOriginalWidth = field.width();\r\n " + );
" fieldOriginalHeight = field.height();\r\n " +
" field.css(\'overflow\', \'visible\').animate({ width: field.par" + field.focus(function () {
"ent().width() - 42, height: 75 }, 200);\r\n }).blur" + fieldOriginalWidth = field.width();
"(function () {\r\n field.css(\'overflow\', \'hidde" + fieldOriginalHeight = field.height();
"n\').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200);\r\n " + field.css('overflow', 'visible').animate({ width: field.parent().width() - 42, height: 75 }, 200);
" }).change(function () {\r\n " + }).blur(function () {
" if (!!field.val()) {\r\n fieldR" + field.css('overflow', 'hidden').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200);
"emove.show();\r\n } else {\r\n " + }).change(function () {
" fieldRemove.hide();\r\n }\r" + if (!!field.val()) {
"\n }).attr(\'placeholder\', \'None\').attr(\'spellcheck" + fieldRemove.show();
"\', \'false\');\r\n\r\n fieldRemove.click(function () {\r" + } else {
"\n field.val(\'\').change();\r\n " + fieldRemove.hide();
" });\r\n\r\n if (!!field.val()) {\r\n " + }
" fieldRemove.show();\r\n " + }).attr('placeholder', 'None').attr('spellcheck', 'false');
" } else {\r\n fieldRemove.hide();\r\n " +
" }\r\n });\r\n <" + fieldRemove.click(function () {
"/script>\r\n"); field.val('').change();
});
if (!!field.val()) {
fieldRemove.show();
} else {
fieldRemove.hide();
}
});
</script>
");
#line 125 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml" #line 125 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
} }
else else
{ {
if (string.IsNullOrWhiteSpace(Model.OnCloseExpression)) if (string.IsNullOrWhiteSpace(Model.OnDeviceReadyForReturnExpression))
{ {
@@ -401,7 +411,7 @@ WriteLiteral(" ");
#line 135 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml" #line 135 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
Write(Model.OnCloseExpression); Write(Model.OnDeviceReadyForReturnExpression);
#line default #line default
@@ -428,6 +438,194 @@ WriteLiteral(">\r\n <i");
WriteLiteral(" class=\"fa fa-fw fa-info-circle\""); WriteLiteral(" class=\"fa fa-fw fa-info-circle\"");
WriteLiteral(@"></i>This expression will be evaluated whenever a device is flagged as Ready For Return. If the expression has any output it will be added to the job log.
</p>
</div>
</td>
</tr>
<tr>
<th");
WriteLiteral(" style=\"width: 200px\"");
WriteLiteral(">On Close:</th>\r\n <td>\r\n");
#line 149 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
#line default
#line hidden
#line 149 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
if (canConfig)
{
#line default
#line hidden
#line 151 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
Write(Html.EditorFor(model => model.OnCloseExpression));
#line default
#line hidden
#line 151 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
#line default
#line hidden
#line 152 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
Write(AjaxHelpers.AjaxRemove());
#line default
#line hidden
#line 152 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
#line default
#line hidden
#line 153 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
Write(AjaxHelpers.AjaxSave());
#line default
#line hidden
#line 153 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
#line default
#line hidden
#line 154 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
Write(AjaxHelpers.AjaxLoader());
#line default
#line hidden
#line 154 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
#line default
#line hidden
WriteLiteral(" <script");
WriteLiteral(" type=\"text/javascript\"");
WriteLiteral(@">
$(function () {
var field = $('#OnCloseExpression');
var fieldRemove = field.next('.ajaxRemove');
var fieldOriginalWidth, fieldOriginalHeight;
document.DiscoFunctions.PropertyChangeHelper(
field,
'None',
'");
#line 164 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
Write(Url.Action(MVC.API.JobPreferences.UpdateOnCloseExpression()));
#line default
#line hidden
WriteLiteral("\',\r\n \'OnCloseExpression\'\r\n " +
" );\r\n\r\n field.focus(function () {\r\n " +
" fieldOriginalWidth = field.width();\r\n " +
" fieldOriginalHeight = field.height();\r\n " +
" field.css(\'overflow\', \'visible\').animate({ width: field.par" +
"ent().width() - 42, height: 75 }, 200);\r\n }).blur" +
"(function () {\r\n field.css(\'overflow\', \'hidde" +
"n\').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200);\r\n " +
" }).change(function () {\r\n " +
" if (!!field.val()) {\r\n fieldR" +
"emove.show();\r\n } else {\r\n " +
" fieldRemove.hide();\r\n }\r" +
"\n }).attr(\'placeholder\', \'None\').attr(\'spellcheck" +
"\', \'false\');\r\n\r\n fieldRemove.click(function () {\r" +
"\n field.val(\'\').change();\r\n " +
" });\r\n\r\n if (!!field.val()) {\r\n " +
" fieldRemove.show();\r\n " +
" } else {\r\n fieldRemove.hide();\r\n " +
" }\r\n });\r\n <" +
"/script>\r\n");
#line 193 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
}
else
{
if (string.IsNullOrWhiteSpace(Model.OnCloseExpression))
{
#line default
#line hidden
WriteLiteral(" <span");
WriteLiteral(" class=\"smallMessage\"");
WriteLiteral(">&lt;None Specified&gt;</span>\r\n");
#line 199 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" class=\"code\"");
WriteLiteral(">\r\n");
WriteLiteral(" ");
#line 203 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
Write(Model.OnCloseExpression);
#line default
#line hidden
WriteLiteral("\r\n </div>\r\n");
#line 205 "..\..\Areas\Config\Views\JobPreferences\Parts\Expressions.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" class=\"info-box\"");
WriteLiteral(">\r\n <p");
WriteLiteral(" class=\"fa-p\"");
WriteLiteral(">\r\n <i");
WriteLiteral(" class=\"fa fa-fw fa-info-circle\"");
WriteLiteral("></i>This expression will be evaluated whenever a job is closed. If the expressio" + WriteLiteral("></i>This expression will be evaluated whenever a job is closed. If the expressio" +
"n has any output it will be added to the job log.\r\n </p>\r\n " + "n has any output it will be added to the job log.\r\n </p>\r\n " +
" </div>\r\n </td>\r\n </tr>\r\n </table>\r\n</div>"); " </div>\r\n </td>\r\n </tr>\r\n </table>\r\n</div>");
@@ -1,5 +1,4 @@
@model Disco.Web.Areas.Config.Models.Plugins.IndexViewModel @model Disco.Web.Areas.Config.Models.Plugins.IndexViewModel
@using Disco.Services.Plugins;
@{ @{
Authorization.Require(Claims.Config.Plugin.Show); Authorization.Require(Claims.Config.Plugin.Show);
@@ -19,7 +18,7 @@
} }
else else
{ {
var pluginGroups = Model.PluginManifestsByCategory; var pluginGroups = Model.PluginManifestsByCategory.OrderBy(c => c.Key).ToList();
int itemsPerColumn = pluginGroups.Count / 3; int itemsPerColumn = pluginGroups.Count / 3;
@@ -37,8 +36,8 @@
var pluginGroup = pluginGroups[itemNextId]; var pluginGroup = pluginGroups[itemNextId];
itemNextId++; itemNextId++;
<div class="pageMenuArea"> <div class="pageMenuArea">
<h2>@Plugins.PluginFeatureCategoryDisplayName(pluginGroup.Item1)</h2> <h2>@pluginGroup.Key</h2>
@foreach (var pluginDefinition in pluginGroup.Item2) @foreach (var pluginDefinition in pluginGroup.Value.OrderBy(p => p.Name))
{ {
if (canConfig) if (canConfig)
{ {
@@ -30,12 +30,6 @@ namespace Disco.Web.Areas.Config.Views.Plugins
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Services; using Disco.Services;
using Disco.Services.Authorization; using Disco.Services.Authorization;
#line 2 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
using Disco.Services.Plugins;
#line default
#line hidden
using Disco.Services.Web; using Disco.Services.Web;
using Disco.Web; using Disco.Web;
using Disco.Web.Extensions; using Disco.Web.Extensions;
@@ -50,7 +44,7 @@ namespace Disco.Web.Areas.Config.Views.Plugins
public override void Execute() public override void Execute()
{ {
#line 3 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 2 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Authorization.Require(Claims.Config.Plugin.Show); Authorization.Require(Claims.Config.Plugin.Show);
@@ -70,13 +64,13 @@ WriteLiteral(" id=\"plugins\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 13 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 12 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 13 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 12 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
if (Model.PluginManifests.Count == 0) if (Model.PluginManifests.Count == 0)
{ {
@@ -93,11 +87,11 @@ WriteLiteral(" style=\"width: 450px; padding: 100px 0;\"");
WriteLiteral(">\r\n <h2>No Plugins are Installed</h2>\r\n </div> \r\n"); WriteLiteral(">\r\n <h2>No Plugins are Installed</h2>\r\n </div> \r\n");
#line 19 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 18 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
else else
{ {
var pluginGroups = Model.PluginManifestsByCategory; var pluginGroups = Model.PluginManifestsByCategory.OrderBy(c => c.Key).ToList();
int itemsPerColumn = pluginGroups.Count / 3; int itemsPerColumn = pluginGroups.Count / 3;
@@ -114,13 +108,13 @@ WriteLiteral(" id=\"pageMenu\"");
WriteLiteral(">\r\n <tr>\r\n"); WriteLiteral(">\r\n <tr>\r\n");
#line 30 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 29 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 30 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 29 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
@@ -130,13 +124,13 @@ WriteLiteral(">\r\n <tr>\r\n");
WriteLiteral(" <td>\r\n"); WriteLiteral(" <td>\r\n");
#line 33 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 32 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 33 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 32 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
int itemsForThisColumn = itemsPerColumn + (pluginGroups.Count % 3 > i ? 1 : 0); int itemsForThisColumn = itemsPerColumn + (pluginGroups.Count % 3 > i ? 1 : 0);
for (int i2 = 0; i2 < itemsForThisColumn && itemNextId < pluginGroups.Count; i2++) for (int i2 = 0; i2 < itemsForThisColumn && itemNextId < pluginGroups.Count; i2++)
@@ -154,8 +148,8 @@ WriteLiteral(" class=\"pageMenuArea\"");
WriteLiteral(">\r\n <h2>"); WriteLiteral(">\r\n <h2>");
#line 40 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 39 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Plugins.PluginFeatureCategoryDisplayName(pluginGroup.Item1)); Write(pluginGroup.Key);
#line default #line default
@@ -163,14 +157,14 @@ WriteLiteral(">\r\n <h2>");
WriteLiteral("</h2>\r\n"); WriteLiteral("</h2>\r\n");
#line 41 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 40 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 41 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 40 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
foreach (var pluginDefinition in pluginGroup.Item2) foreach (var pluginDefinition in pluginGroup.Value.OrderBy(p => p.Name))
{ {
if (canConfig) if (canConfig)
{ {
@@ -180,14 +174,14 @@ WriteLiteral("</h2>\r\n");
#line hidden #line hidden
WriteLiteral(" <a"); WriteLiteral(" <a");
WriteAttribute("href", Tuple.Create(" href=\"", 1807), Tuple.Create("\"", 1876) WriteAttribute("href", Tuple.Create(" href=\"", 1781), Tuple.Create("\"", 1850)
#line 45 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 44 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
, Tuple.Create(Tuple.Create("", 1814), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.Config.Plugins.Configure(pluginDefinition.Id)) , Tuple.Create(Tuple.Create("", 1788), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.Config.Plugins.Configure(pluginDefinition.Id))
#line default #line default
#line hidden #line hidden
, 1814), false) , 1788), false)
); );
WriteLiteral(">\r\n <i"); WriteLiteral(">\r\n <i");
@@ -197,7 +191,7 @@ WriteLiteral(" class=\"fa fa-cogs\"");
WriteLiteral("></i>\r\n <h3>"); WriteLiteral("></i>\r\n <h3>");
#line 47 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 46 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(pluginDefinition.Name); Write(pluginDefinition.Name);
@@ -206,7 +200,7 @@ WriteLiteral("></i>\r\n <h3>");
WriteLiteral("</h3>\r\n </a>\r\n"); WriteLiteral("</h3>\r\n </a>\r\n");
#line 49 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 48 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
else else
{ {
@@ -217,7 +211,7 @@ WriteLiteral("</h3>\r\n </a>\r\n");
WriteLiteral(" <h3>"); WriteLiteral(" <h3>");
#line 52 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 51 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(pluginDefinition.Name); Write(pluginDefinition.Name);
@@ -226,7 +220,7 @@ WriteLiteral(" <h3>");
WriteLiteral("</h3>\r\n"); WriteLiteral("</h3>\r\n");
#line 53 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 52 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
@@ -243,7 +237,7 @@ WriteLiteral(" class=\"pluginVersion\"");
WriteLiteral(">v"); WriteLiteral(">v");
#line 55 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 54 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(pluginDefinition.VersionFormatted); Write(pluginDefinition.VersionFormatted);
@@ -252,7 +246,7 @@ WriteLiteral(">v");
WriteLiteral("</span> | "); WriteLiteral("</span> | ");
#line 55 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 54 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(pluginDefinition.Author); Write(pluginDefinition.Author);
@@ -260,14 +254,14 @@ WriteLiteral("</span> | ");
#line hidden #line hidden
WriteLiteral(" | <a"); WriteLiteral(" | <a");
WriteAttribute("href", Tuple.Create(" href=\"", 2500), Tuple.Create("\"", 2528) WriteAttribute("href", Tuple.Create(" href=\"", 2474), Tuple.Create("\"", 2502)
#line 55 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 54 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
, Tuple.Create(Tuple.Create("", 2507), Tuple.Create<System.Object, System.Int32>(pluginDefinition.Url , Tuple.Create(Tuple.Create("", 2481), Tuple.Create<System.Object, System.Int32>(pluginDefinition.Url
#line default #line default
#line hidden #line hidden
, 2507), false) , 2481), false)
); );
WriteLiteral(" title=\"More Information\""); WriteLiteral(" title=\"More Information\"");
@@ -281,7 +275,7 @@ WriteLiteral(" class=\"fa fa-external-link\"");
WriteLiteral("></i></a>\r\n </div>\r\n"); WriteLiteral("></i></a>\r\n </div>\r\n");
#line 57 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 56 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
@@ -290,7 +284,7 @@ WriteLiteral("></i></a>\r\n </div>\r\n");
WriteLiteral(" </div>\r\n"); WriteLiteral(" </div>\r\n");
#line 59 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 58 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
@@ -299,7 +293,7 @@ WriteLiteral(" </div>\r\n");
WriteLiteral("\r\n </td>\r\n"); WriteLiteral("\r\n </td>\r\n");
#line 62 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 61 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
@@ -308,7 +302,7 @@ WriteLiteral("\r\n </td>\r\n");
WriteLiteral(" </tr>\r\n </table>\r\n"); WriteLiteral(" </tr>\r\n </table>\r\n");
#line 65 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 64 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
if (canUninstall) if (canUninstall)
{ {
@@ -326,7 +320,7 @@ WriteLiteral(">\r\n <div>\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 69 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 68 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Html.DropDownList("uninstallPlugin", Model.PluginManifests.ToSelectListItems(null, true, "Select a Plugin to Uninstall"))); Write(Html.DropDownList("uninstallPlugin", Model.PluginManifests.ToSelectListItems(null, true, "Select a Plugin to Uninstall")));
@@ -407,7 +401,7 @@ WriteLiteral(" <script>\r\n $(function () {\r\n
" var uninstallUrl = \'"); " var uninstallUrl = \'");
#line 96 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 95 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Url.Action(MVC.API.Plugin.Uninstall())); Write(Url.Action(MVC.API.Plugin.Uninstall()));
@@ -460,7 +454,7 @@ WriteLiteral("/\';\r\n var uninstallPlugin, uninstallPluginData,
"}\r\n });\r\n });\r\n </script>\r\n"); "}\r\n });\r\n });\r\n </script>\r\n");
#line 176 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 175 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
if (Model.PluginUpdates.Count > 0) if (Model.PluginUpdates.Count > 0)
{ {
@@ -479,7 +473,7 @@ WriteLiteral(" class=\"fa fa-cloud-download\"");
WriteLiteral("></i>\r\n <div>"); WriteLiteral("></i>\r\n <div>");
#line 181 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 180 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Model.PluginUpdates.Count); Write(Model.PluginUpdates.Count);
@@ -488,7 +482,7 @@ WriteLiteral("></i>\r\n <div>");
WriteLiteral(" plugin update"); WriteLiteral(" plugin update");
#line 181 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 180 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Model.PluginUpdates.Count == 1 ? " is" : "s are"); Write(Model.PluginUpdates.Count == 1 ? " is" : "s are");
@@ -497,13 +491,13 @@ WriteLiteral(" plugin update");
WriteLiteral(" available</div>\r\n"); WriteLiteral(" available</div>\r\n");
#line 182 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 181 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 182 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 181 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
if (canInstall) if (canInstall)
{ {
@@ -511,14 +505,14 @@ WriteLiteral(" available</div>\r\n");
#line default #line default
#line hidden #line hidden
#line 184 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 183 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Html.ActionLinkSmallButton("Update Now", MVC.API.Plugin.UpdateAll(), null, "alert")); Write(Html.ActionLinkSmallButton("Update Now", MVC.API.Plugin.UpdateAll(), null, "alert"));
#line default #line default
#line hidden #line hidden
#line 184 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 183 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
else else
@@ -534,7 +528,7 @@ WriteLiteral(" class=\"smallMessage\"");
WriteLiteral(">You do not have sufficient permission to install these updates.</div>\r\n"); WriteLiteral(">You do not have sufficient permission to install these updates.</div>\r\n");
#line 189 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 188 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
@@ -554,7 +548,7 @@ WriteLiteral(@" <script>
"); ");
#line 200 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 199 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
} }
@@ -568,13 +562,13 @@ WriteLiteral(" class=\"actionBar\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 205 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 204 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
#line default #line default
#line hidden #line hidden
#line 205 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 204 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
if (canUninstall && Model.PluginManifests.Count > 0) if (canUninstall && Model.PluginManifests.Count > 0)
{ {
@@ -582,14 +576,14 @@ WriteLiteral(">\r\n");
#line default #line default
#line hidden #line hidden
#line 207 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 206 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Html.ActionLinkButton("Uninstall Plugins", MVC.Config.Plugins.Index(), "buttonUninstall")); Write(Html.ActionLinkButton("Uninstall Plugins", MVC.Config.Plugins.Index(), "buttonUninstall"));
#line default #line default
#line hidden #line hidden
#line 207 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 206 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
@@ -599,7 +593,7 @@ WriteLiteral(">\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 209 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 208 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
if (canInstall) if (canInstall)
{ {
@@ -607,14 +601,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 211 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 210 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
Write(Html.ActionLinkButton("Install Plugins", MVC.Config.Plugins.Install())); Write(Html.ActionLinkButton("Install Plugins", MVC.Config.Plugins.Install()));
#line default #line default
#line hidden #line hidden
#line 211 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line 210 "..\..\Areas\Config\Views\Plugins\Index.cshtml"
} }
@@ -41,7 +41,7 @@
{ {
if (Version.Parse(plugin.Item2.Version) > installedPlugin.Version) if (Version.Parse(plugin.Item2.Version) > installedPlugin.Version)
{ {
<a class="pluginUpdateLink button" href="@(Url.Action(MVC.API.Plugin.Update(plugin.Item1.Id)))">Update</a> <a class="pluginUpdateLink button alert" href="@(Url.Action(MVC.API.Plugin.Update(plugin.Item1.Id)))">Update</a>
} }
else else
{ {
@@ -243,16 +243,16 @@ WriteLiteral(">Install</a>\r\n");
#line hidden #line hidden
WriteLiteral(" <a"); WriteLiteral(" <a");
WriteLiteral(" class=\"pluginUpdateLink button\""); WriteLiteral(" class=\"pluginUpdateLink button alert\"");
WriteAttribute("href", Tuple.Create(" href=\"", 2412), Tuple.Create("\"", 2472) WriteAttribute("href", Tuple.Create(" href=\"", 2418), Tuple.Create("\"", 2478)
#line 44 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 44 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 2419), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Update(plugin.Item1.Id)) , Tuple.Create(Tuple.Create("", 2425), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Update(plugin.Item1.Id))
#line default #line default
#line hidden #line hidden
, 2419), false) , 2425), false)
); );
WriteLiteral(">Update</a>\r\n"); WriteLiteral(">Update</a>\r\n");
@@ -270,14 +270,14 @@ WriteLiteral(" <a");
WriteLiteral(" class=\"button\""); WriteLiteral(" class=\"button\"");
WriteAttribute("href", Tuple.Create(" href=\"", 2711), Tuple.Create("\"", 2778) WriteAttribute("href", Tuple.Create(" href=\"", 2717), Tuple.Create("\"", 2784)
#line 48 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 48 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 2718), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.Config.Plugins.Configure(plugin.Item1.Id)) , Tuple.Create(Tuple.Create("", 2724), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.Config.Plugins.Configure(plugin.Item1.Id))
#line default #line default
#line hidden #line hidden
, 2718), false) , 2724), false)
); );
WriteLiteral(">Configure</a>\r\n"); WriteLiteral(">Configure</a>\r\n");
@@ -345,14 +345,14 @@ WriteLiteral("</span> | ");
#line hidden #line hidden
WriteLiteral(" | <a"); WriteLiteral(" | <a");
WriteAttribute("href", Tuple.Create(" href=\"", 3309), Tuple.Create("\"", 3344) WriteAttribute("href", Tuple.Create(" href=\"", 3315), Tuple.Create("\"", 3350)
#line 54 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 54 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 3316), Tuple.Create<System.Object, System.Int32>(plugin.Item1.InformationUrl , Tuple.Create(Tuple.Create("", 3322), Tuple.Create<System.Object, System.Int32>(plugin.Item1.InformationUrl
#line default #line default
#line hidden #line hidden
, 3316), false) , 3322), false)
); );
WriteLiteral(" title=\"More Information\""); WriteLiteral(" title=\"More Information\"");
@@ -69,6 +69,86 @@
</tr> </tr>
</table> </table>
</div> </div>
<div class="form" style="width: 450px; margin-top: 15px;">
<h2>License</h2>
<table>
@{
<tr>
<th style="width: 135px">
License:
</th>
<td>
@using (Html.BeginForm(MVC.API.System.LicenseCheck(), FormMethod.Post))
{
@Html.AntiForgeryToken();
<input id="license" type="text" name="license" value="@Model.License" />
<button type="submit" class="button small">Activate</button>
}
<script type="text/javascript">
$(function () {
const $element = $('#license');
const original = $element.val();
$element.on('keyup', function (e) {
const $button = $element.next('button');
const value = $element.val();
if (!original) {
$element.prop('required', true);
$button.text('Activate');
} else {
if (original === value) {
$button.text('Validate');
} else {
if (!value) {
$button.text('Clear');
} else {
$button.text('Activate');
}
}
}
}).trigger('keyup');
});
</script>
</td>
</tr>
if (Model.License != null)
{
<tr>
<th style="width: 135px">
Status:
</th>
<td>
@if (Model.LicenseError != null)
{
<div class="error"><i class="fa fa-exclamation-circle fa-lg"></i> @Model.LicenseError</div>
}
else
{
<span>Expires @CommonHelpers.FriendlyDate(Model.LicenseExpires)</span>
}
</td>
</tr>
}
else
{
<tr>
<td colspan="2">
<strong>Official support is available</strong>
<ul>
<li>Initial implementation assistance.</li>
<li>Commitment to maintaining Disco ICT functionality and associated plugins.</li>
<li>Direct support.</li>
<li>Access to additional functionality.</li>
<li>Ability to suggest additional functionality, with a voice in feature prioritisation.</li>
</ul>
<div style="text-align: right; margin-top: 4px;">
<a href="https://discoict.com.au/support.aspx" target="_blank" class="button small">Request More Information</a>
</div>
</td>
</tr>
}
}
</table>
</div>
<div class="form" style="width: 450px; margin-top: 15px;"> <div class="form" style="width: 450px; margin-top: 15px;">
<h2>Updates</h2> <h2>Updates</h2>
<table> <table>
File diff suppressed because it is too large Load Diff
+14 -4
View File
@@ -473,6 +473,10 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.message {
#enrolStatus #sessions .session > h3 span.details { #enrolStatus #sessions .session > h3 span.details {
font-size: 0.8em; font-size: 0.8em;
} }
#enrolStatus #sessions .session > h3 span.pending {
float: right;
color: #F0A30A;
}
#enrolStatus #sessions .session > p.sessionStart { #enrolStatus #sessions .session > p.sessionStart {
color: #888; color: #888;
font-size: 0.8em; font-size: 0.8em;
@@ -489,7 +493,6 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.message {
background-color: #DFE1F8; background-color: #DFE1F8;
} }
#dialogSession .sessionHeader { #dialogSession .sessionHeader {
width: 400px;
float: left; float: left;
padding: 0 0 0 134px; padding: 0 0 0 134px;
background-repeat: no-repeat, no-repeat; background-repeat: no-repeat, no-repeat;
@@ -516,7 +519,8 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.message {
} }
#dialogSession .sessionProgress { #dialogSession .sessionProgress {
width: 320px; width: 320px;
float: right; position: absolute;
right: 1em;
text-align: right; text-align: right;
} }
#dialogSession .sessionProgress > p.sessionStart { #dialogSession .sessionProgress > p.sessionStart {
@@ -528,6 +532,13 @@ div.logEventsViewport table.logEventsViewport > tbody > tr > td.message {
overflow: hidden; overflow: hidden;
margin-bottom: 3px; margin-bottom: 3px;
} }
#dialogSession .sessionProgress code {
font-size: 2em;
color: #E51400;
}
#dialogSession .sessionProgress div.reason {
margin-bottom: 3px;
}
#dialogSession .sessionInfoContainer > div { #dialogSession .sessionInfoContainer > div {
float: left; float: left;
width: 428px; width: 428px;
@@ -1542,8 +1553,7 @@ h1.Config_DocumentTemplates {
#Config_JobPref_Expressions { #Config_JobPref_Expressions {
margin-top: 10px; margin-top: 10px;
} }
#Config_JobPref_Expressions #OnCreateExpression, #Config_JobPref_Expressions textarea {
#Config_JobPref_Expressions #OnCloseExpression {
height: 16px; height: 16px;
min-height: 16px; min-height: 16px;
overflow: hidden; overflow: hidden;
+17 -3
View File
@@ -479,6 +479,11 @@ div.logEventsViewport {
span.details { span.details {
font-size: .8em; font-size: .8em;
} }
span.pending {
float: right;
color: @ThemeAmber;
}
} }
& > p.sessionStart { & > p.sessionStart {
@@ -504,7 +509,6 @@ div.logEventsViewport {
#dialogSession { #dialogSession {
.sessionHeader { .sessionHeader {
width: 400px;
float: left; float: left;
padding: 0 0 0 134px; padding: 0 0 0 134px;
background-repeat: no-repeat, no-repeat; background-repeat: no-repeat, no-repeat;
@@ -535,7 +539,8 @@ div.logEventsViewport {
.sessionProgress { .sessionProgress {
width: 320px; width: 320px;
float: right; position: absolute;
right: 1em;
text-align: right; text-align: right;
& > p.sessionStart { & > p.sessionStart {
@@ -548,6 +553,15 @@ div.logEventsViewport {
overflow: hidden; overflow: hidden;
margin-bottom: 3px; margin-bottom: 3px;
} }
& code {
font-size: 2em;
color: @ThemeRed;
}
& div.reason {
margin-bottom: 3px;
}
} }
.sessionInfoContainer { .sessionInfoContainer {
@@ -1793,7 +1807,7 @@ h1.Config_DocumentTemplates {
#Config_JobPref_Expressions { #Config_JobPref_Expressions {
margin-top: 10px; margin-top: 10px;
#OnCreateExpression, #OnCloseExpression { textarea {
height: 16px; height: 16px;
min-height: 16px; min-height: 16px;
overflow: hidden; overflow: hidden;
File diff suppressed because one or more lines are too long
+34 -4
View File
@@ -97,6 +97,32 @@
height: 50px; height: 50px;
font-size: 0.6em; font-size: 0.6em;
} }
#layout_PageHeading #pendingEnrollments {
position: relative;
float: right;
border: 1px dashed #ddd;
background-color: #fff;
font-size: 0.6em;
line-height: 1em;
padding: 10px 10px 4px 70px;
text-align: right;
height: 50px;
}
#layout_PageHeading #pendingEnrollments i {
position: absolute;
display: block;
height: 64px;
width: 64px;
vertical-align: middle;
margin-left: -75px;
top: 8px;
font-size: 50px;
color: #e51400;
}
#layout_PageHeading #pendingEnrollments a.button {
font-size: 12px;
margin-top: 8px;
}
#Jobs_Index_MyJobs { #Jobs_Index_MyJobs {
margin-bottom: 10px; margin-bottom: 10px;
} }
@@ -853,18 +879,22 @@
margin-right: 10px; margin-right: 10px;
color: #1e6dab; color: #1e6dab;
} }
#repairJobForm #repairDisclosedInformation table { #repairJobForm #disclosedInformation table,
#insuranceJobForm #disclosedInformation table {
font-size: 0.9em; font-size: 0.9em;
} }
#repairJobForm #repairDisclosedInformation table tr:not(:last-child) { #repairJobForm #disclosedInformation table tr:not(:last-child),
#insuranceJobForm #disclosedInformation table tr:not(:last-child) {
border-bottom: 1px dashed #aaa; border-bottom: 1px dashed #aaa;
} }
#repairJobForm #repairDisclosedInformation table th { #repairJobForm #disclosedInformation table th,
#insuranceJobForm #disclosedInformation table th {
padding: 2px; padding: 2px;
font-weight: 600; font-weight: 600;
width: 200px; width: 200px;
} }
#repairJobForm #repairDisclosedInformation table td { #repairJobForm #disclosedInformation table td,
#insuranceJobForm #disclosedInformation table td {
padding: 2px; padding: 2px;
} }
#repairJobRepairDescription #RepairDescription { #repairJobRepairDescription #RepairDescription {
+31 -2
View File
@@ -25,6 +25,35 @@
height: 50px; height: 50px;
font-size: 0.6em; font-size: 0.6em;
} }
#pendingEnrollments {
position: relative;
float: right;
border: 1px dashed #ddd;
background-color: @white;
font-size: 0.6em;
line-height: 1em;
padding: 10px 10px 4px 70px;
text-align: right;
height: 50px;
i {
position: absolute;
display: block;
height: 64px;
width: 64px;
vertical-align: middle;
margin-left: -75px;
top: 8px;
font-size: 50px;
color: @ButtonAlertColour;
}
a.button {
font-size: @FontSizeDefault;
margin-top: 8px;
}
}
} }
#Jobs_Index_MyJobs { #Jobs_Index_MyJobs {
@@ -911,8 +940,8 @@
} }
} }
#repairJobForm { #repairJobForm, #insuranceJobForm {
#repairDisclosedInformation { #disclosedInformation {
table { table {
font-size: 0.9em; font-size: 0.9em;
File diff suppressed because one or more lines are too long
+191 -7
View File
@@ -4,12 +4,14 @@ using Disco.Models.Services.Jobs.JobLists;
using Disco.Models.UI.Job; using Disco.Models.UI.Job;
using Disco.Services; using Disco.Services;
using Disco.Services.Authorization; using Disco.Services.Authorization;
using Disco.Services.Devices.Enrolment;
using Disco.Services.Jobs; using Disco.Services.Jobs;
using Disco.Services.Jobs.JobLists; using Disco.Services.Jobs.JobLists;
using Disco.Services.Jobs.JobQueues; using Disco.Services.Jobs.JobQueues;
using Disco.Services.Jobs.Statistics; using Disco.Services.Jobs.Statistics;
using Disco.Services.Logging; using Disco.Services.Logging;
using Disco.Services.Plugins.Features.DetailsProvider; using Disco.Services.Plugins.Features.DetailsProvider;
using Disco.Services.Plugins.Features.InsuranceProvider;
using Disco.Services.Plugins.Features.RepairProvider; using Disco.Services.Plugins.Features.RepairProvider;
using Disco.Services.Plugins.Features.UIExtension; using Disco.Services.Plugins.Features.UIExtension;
using Disco.Services.Plugins.Features.WarrantyProvider; using Disco.Services.Plugins.Features.WarrantyProvider;
@@ -46,6 +48,9 @@ namespace Disco.Web.Controllers
if (Authorization.Has(Claims.Job.ShowDailyChart)) if (Authorization.Has(Claims.Job.ShowDailyChart))
m.DailyOpenedClosedStatistics = DailyOpenedClosed.Data(Database, true); m.DailyOpenedClosedStatistics = DailyOpenedClosed.Data(Database, true);
if (Authorization.Has(Claims.Device.Actions.EnrolDevices))
m.PendingEnrollments = WindowsDeviceEnrolment.GetPendingEnrolments();
// UI Extensions // UI Extensions
UIExtensions.ExecuteExtensions<JobIndexModel>(this.ControllerContext, m); UIExtensions.ExecuteExtensions<JobIndexModel>(this.ControllerContext, m);
@@ -549,7 +554,7 @@ namespace Disco.Web.Controllers
return View(m); return View(m);
} }
[HttpPost, DiscoAuthorize(Claims.Job.Actions.LogWarranty)] [HttpPost, ValidateAntiForgeryToken, DiscoAuthorize(Claims.Job.Actions.LogWarranty), ValidateInput(false)]
public virtual ActionResult LogWarranty(Models.Job.LogWarrantyModel m, FormCollection form) public virtual ActionResult LogWarranty(Models.Job.LogWarrantyModel m, FormCollection form)
{ {
m.UpdateModel(Database, true); m.UpdateModel(Database, true);
@@ -732,7 +737,7 @@ namespace Disco.Web.Controllers
return View(m); return View(m);
} }
[HttpPost, DiscoAuthorize(Claims.Job.Actions.LogRepair)] [HttpPost, ValidateAntiForgeryToken, DiscoAuthorize(Claims.Job.Actions.LogRepair), ValidateInput(false)]
public virtual ActionResult LogRepair(Models.Job.LogRepairModel m, FormCollection form) public virtual ActionResult LogRepair(Models.Job.LogRepairModel m, FormCollection form)
{ {
m.UpdateModel(Database, true); m.UpdateModel(Database, true);
@@ -755,12 +760,9 @@ namespace Disco.Web.Controllers
if (updatedModel.RepairProvider != null) if (updatedModel.RepairProvider != null)
{ {
using (var wp = updatedModel.RepairProvider.CreateInstance<RepairProviderFeature>()) using (var rp = m.RepairProvider.CreateInstance<RepairProviderFeature>())
{ {
using (var rp = m.RepairProvider.CreateInstance<RepairProviderFeature>()) updatedModel.RepairProviderSubmitJobBeginResult = rp.SubmitJobBegin(Database, this, updatedModel.Job, updatedModel.OrganisationAddress, updatedModel.TechUser);
{
m.RepairProviderSubmitJobBeginResult = rp.SubmitJobBegin(Database, this, updatedModel.Job, updatedModel.OrganisationAddress, updatedModel.TechUser);
}
} }
} }
@@ -891,5 +893,187 @@ namespace Disco.Web.Controllers
} }
#endregion #endregion
#region Log Insurance
[DiscoAuthorizeAny(Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent, Claims.Job.Actions.LogInsurance)]
public virtual ActionResult LogInsurance(int id, string providerId, int? organisationAddressId)
{
var m = new Models.Job.LogInsuranceModel()
{
JobId = id,
ProviderId = providerId,
OrganisationAddressId = organisationAddressId
};
m.UpdateModel(Database, false);
if (m.Provider != null)
{
using (var rp = m.Provider.CreateInstance<InsuranceProviderFeature>())
{
m.ProviderSubmitJobBeginResult = rp.SubmitJobBegin(Database, this, m.Job, m.OrganisationAddress, m.TechUser);
}
}
return View(m);
}
[HttpPost, ValidateAntiForgeryToken, DiscoAuthorizeAny(Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent, Claims.Job.Actions.LogInsurance), ValidateInput(false)]
public virtual ActionResult LogInsurance(Models.Job.LogInsuranceModel m, FormCollection form)
{
m.UpdateModel(Database, true);
if (ModelState.IsValid)
{
switch (m.SubmissionAction)
{
case "Update":
var updatedModel = new Models.Job.LogInsuranceModel()
{
JobId = m.JobId,
ProviderId = m.ProviderId,
OrganisationAddressId = m.OrganisationAddressId,
AttachmentIds = m.AttachmentIds,
Attachments = m.Attachments
};
updatedModel.UpdateModel(Database, false);
if (updatedModel.Provider != null)
{
using (var ip = updatedModel.Provider.CreateInstance<InsuranceProviderFeature>())
{
updatedModel.ProviderSubmitJobBeginResult = ip.SubmitJobBegin(Database, this, updatedModel.Job, updatedModel.OrganisationAddress, updatedModel.TechUser);
}
}
return View(updatedModel);
case "Manual":
if (string.IsNullOrWhiteSpace(m.ManualProviderName))
{
ModelState.AddModelError("ManualProviderName", "The Provider Name is required");
return View(m);
}
try
{
m.Job.OnLogInsurance(Database, 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.LogInsuranceError, m);
throw;
}
case "Disclose":
using (var p = m.Provider.CreateInstance<InsuranceProviderFeature>())
{
Dictionary<string, string> providerProperties;
try
{
providerProperties = p.SubmitJobParseProperties(Database, form, this, m.Job, m.OrganisationAddress, m.TechUser);
}
catch (Exception ex)
{
m.Error = ex;
return View(Views.LogInsuranceError, m);
}
if (!ModelState.IsValid)
return View(Views.LogInsurance, m);
if (providerProperties != null)
{
m.ProviderPropertiesJson = JsonConvert.SerializeObject(providerProperties);
}
m.DiscloseProperties = p.SubmitJobDiscloseInfo(Database, m.Job, m.OrganisationAddress, m.TechUser, providerProperties);
return View(Views.LogInsuranceDisclose, m);
}
case "Submit":
try
{
m.Job.OnLogInsurance(Database, m.Attachments, m.Provider, m.OrganisationAddress, m.TechUser, m.ProviderProperties());
Database.SaveChanges();
return RedirectToAction(MVC.Job.Show(m.JobId));
}
catch (Exception ex)
{
m.Error = ex;
return View(Views.LogInsuranceError, m);
throw;
}
default:
return RedirectToAction(MVC.Job.Show(m.JobId));
}
}
else
{
return View(m);
}
}
[DiscoAuthorize(Claims.Job.Properties.NonWarrantyProperties.InsuranceDetails)]
public virtual ActionResult InsuranceProviderJobDetails(int id)
{
var model = new Models.Job.ProviderJobDetailsModel();
Job job = Database.Jobs
.Include(j => j.Device.DeviceModel)
.Include(j => j.JobMetaNonWarranty)
.Include(j => j.JobMetaInsurance)
.Include(j => j.JobSubTypes)
.Where(j => j.Id == id).FirstOrDefault();
if (job != null)
{
if (job.JobMetaInsurance != null && !string.IsNullOrEmpty(job.JobMetaInsurance.Insurer))
{
var providerDef = InsuranceProviderFeature.FindPluginFeature(job.JobMetaInsurance.Insurer);
if (providerDef != null)
{
using (var providerInstance = providerDef.CreateInstance<InsuranceProviderFeature>())
{
if (providerInstance.JobDetailsSupported)
{
try
{
Tuple<Type, dynamic> 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 = $"Plugin '{providerInstance.Manifest.Name} ({providerInstance.Manifest.Id})' (Insurance Provider for '{providerInstance.ProviderId}') doesn't support Job Details";
return View(model);
}
}
}
model.JobDetailsSupported = false;
model.JobDetailsNotSupportedMessage = $"Repair Provider '{job.JobMetaNonWarranty.RepairerName}' is not integrated with Disco ICT";
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
} }
} }
+54 -13
View File
@@ -208,6 +208,7 @@
<Compile Include="Areas\API\Controllers\AuthorizationRoleController.cs" /> <Compile Include="Areas\API\Controllers\AuthorizationRoleController.cs" />
<Compile Include="Areas\API\Controllers\DocumentTemplatePackageController.cs" /> <Compile Include="Areas\API\Controllers\DocumentTemplatePackageController.cs" />
<Compile Include="Areas\API\Controllers\DeviceFlagAssignmentController.cs" /> <Compile Include="Areas\API\Controllers\DeviceFlagAssignmentController.cs" />
<Compile Include="Areas\API\Controllers\EnrollmentController.cs" />
<Compile Include="Areas\API\Controllers\UserFlagAssignmentController.cs" /> <Compile Include="Areas\API\Controllers\UserFlagAssignmentController.cs" />
<Compile Include="Areas\API\Controllers\DeviceFlagController.cs" /> <Compile Include="Areas\API\Controllers\DeviceFlagController.cs" />
<Compile Include="Areas\API\Controllers\UserFlagController.cs" /> <Compile Include="Areas\API\Controllers\UserFlagController.cs" />
@@ -678,6 +679,9 @@
<Compile Include="Extensions\T4MVC\API.DocumentTemplatePackageController.generated.cs"> <Compile Include="Extensions\T4MVC\API.DocumentTemplatePackageController.generated.cs">
<DependentUpon>T4MVC.tt</DependentUpon> <DependentUpon>T4MVC.tt</DependentUpon>
</Compile> </Compile>
<Compile Include="Extensions\T4MVC\API.EnrollmentController.generated.cs">
<DependentUpon>T4MVC.tt</DependentUpon>
</Compile>
<Compile Include="Extensions\T4MVC\Config.DeviceFlagController.generated.cs"> <Compile Include="Extensions\T4MVC\Config.DeviceFlagController.generated.cs">
<DependentUpon>T4MVC.tt</DependentUpon> <DependentUpon>T4MVC.tt</DependentUpon>
</Compile> </Compile>
@@ -829,6 +833,7 @@
<Compile Include="Models\Device\ExportModel.cs" /> <Compile Include="Models\Device\ExportModel.cs" />
<Compile Include="Models\Device\ImportHeadersModel.cs" /> <Compile Include="Models\Device\ImportHeadersModel.cs" />
<Compile Include="Models\InitialConfig\AdministratorsModel.cs" /> <Compile Include="Models\InitialConfig\AdministratorsModel.cs" />
<Compile Include="Models\Job\LogInsuranceModel.cs" />
<Compile Include="Models\Job\LogRepairModel.cs" /> <Compile Include="Models\Job\LogRepairModel.cs" />
<Compile Include="Extensions\T4MVC\T4MVC.cs"> <Compile Include="Extensions\T4MVC\T4MVC.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@@ -856,21 +861,41 @@
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
</Compile> </Compile>
<Compile Include="Views\Job\LogInsurance.generated.cs">
<DependentUpon>LogInsurance.cshtml</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Views\Job\LogRepair.generated.cs"> <Compile Include="Views\Job\LogRepair.generated.cs">
<DependentUpon>LogRepair.cshtml</DependentUpon> <DependentUpon>LogRepair.cshtml</DependentUpon>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
</Compile> </Compile>
<Compile Include="Views\Job\LogInsuranceDisclose.generated.cs">
<DependentUpon>LogInsuranceDisclose.cshtml</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Views\Job\LogRepairDisclose.generated.cs"> <Compile Include="Views\Job\LogRepairDisclose.generated.cs">
<DependentUpon>LogRepairDisclose.cshtml</DependentUpon> <DependentUpon>LogRepairDisclose.cshtml</DependentUpon>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
</Compile> </Compile>
<Compile Include="Views\Job\LogInsuranceError.generated.cs">
<DependentUpon>LogInsuranceError.cshtml</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Views\Job\LogRepairError.generated.cs"> <Compile Include="Views\Job\LogRepairError.generated.cs">
<DependentUpon>LogRepairError.cshtml</DependentUpon> <DependentUpon>LogRepairError.cshtml</DependentUpon>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
</Compile> </Compile>
<Compile Include="Views\Job\InsuranceProviderJobDetails.generated.cs">
<DependentUpon>InsuranceProviderJobDetails.cshtml</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Views\Job\RepairProviderJobDetails.generated.cs"> <Compile Include="Views\Job\RepairProviderJobDetails.generated.cs">
<DependentUpon>RepairProviderJobDetails.cshtml</DependentUpon> <DependentUpon>RepairProviderJobDetails.cshtml</DependentUpon>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@@ -1339,30 +1364,30 @@
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>_DeviceGroupDocumentBulkGenerate.generated.cs</LastGenOutput> <LastGenOutput>_DeviceGroupDocumentBulkGenerate.generated.cs</LastGenOutput>
</None> </None>
<Content Include="Areas\Config\Views\DeviceFlag\Create.cshtml"> <None Include="Areas\Config\Views\DeviceFlag\Create.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>Create.generated.cs</LastGenOutput> <LastGenOutput>Create.generated.cs</LastGenOutput>
</Content> </None>
<Content Include="Areas\Config\Views\DeviceFlag\Export.cshtml"> <None Include="Areas\Config\Views\DeviceFlag\Export.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>Export.generated.cs</LastGenOutput> <LastGenOutput>Export.generated.cs</LastGenOutput>
</Content> </None>
<Content Include="Areas\Config\Views\DeviceFlag\Index.cshtml"> <None Include="Areas\Config\Views\DeviceFlag\Index.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>Index.generated.cs</LastGenOutput> <LastGenOutput>Index.generated.cs</LastGenOutput>
</Content> </None>
<Content Include="Areas\Config\Views\DeviceFlag\Show.cshtml"> <None Include="Areas\Config\Views\DeviceFlag\Show.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>Show.generated.cs</LastGenOutput> <LastGenOutput>Show.generated.cs</LastGenOutput>
</Content> </None>
<None Include="Areas\Config\Views\UserFlag\Create.cshtml"> <None Include="Areas\Config\Views\UserFlag\Create.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>Create.generated.cs</LastGenOutput> <LastGenOutput>Create.generated.cs</LastGenOutput>
</None> </None>
<Content Include="Areas\Config\Views\UserFlag\Export.cshtml"> <None Include="Areas\Config\Views\UserFlag\Export.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>Export.generated.cs</LastGenOutput> <LastGenOutput>Export.generated.cs</LastGenOutput>
</Content> </None>
<None Include="Areas\Config\Views\UserFlag\Index.cshtml"> <None Include="Areas\Config\Views\UserFlag\Index.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>Index.generated.cs</LastGenOutput> <LastGenOutput>Index.generated.cs</LastGenOutput>
@@ -1505,7 +1530,7 @@
<DependentUpon>Disco-DataTableHelpers.js</DependentUpon> <DependentUpon>Disco-DataTableHelpers.js</DependentUpon>
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Content Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator\disco.documentgenerator.js" /> <Content Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator\disco.documentgenerator.js" Condition=" '$(Configuration)' == 'Debug' " />
<None Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator.js" /> <None Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator.js" />
<Content Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator.js" Condition=" '$(Configuration)' == 'Debug' " /> <Content Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator.js" Condition=" '$(Configuration)' == 'Debug' " />
<Content Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator.min.js"> <Content Include="ClientSource\Scripts\Modules\Disco-DocumentGenerator.min.js">
@@ -1941,10 +1966,10 @@
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>AddOffline.generated.cs</LastGenOutput> <LastGenOutput>AddOffline.generated.cs</LastGenOutput>
</None> </None>
<Content Include="Views\Device\DeviceParts\_Flags.cshtml"> <None Include="Views\Device\DeviceParts\_Flags.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>_Flags.generated.cs</LastGenOutput> <LastGenOutput>_Flags.generated.cs</LastGenOutput>
</Content> </None>
<None Include="Views\Device\ImportHeaders.cshtml"> <None Include="Views\Device\ImportHeaders.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>ImportHeaders.generated.cs</LastGenOutput> <LastGenOutput>ImportHeaders.generated.cs</LastGenOutput>
@@ -2039,6 +2064,22 @@
<None Include="ClientSource\Scripts\Modules\tinymce\themes\modern\theme.min.js" /> <None Include="ClientSource\Scripts\Modules\tinymce\themes\modern\theme.min.js" />
<None Include="ClientSource\Scripts\Modules\tinymce\tinymce.js" /> <None Include="ClientSource\Scripts\Modules\tinymce\tinymce.js" />
<None Include="ClientSource\Scripts\Modules\tinymce\tinymce.min.js" /> <None Include="ClientSource\Scripts\Modules\tinymce\tinymce.min.js" />
<None Include="Views\Job\LogInsurance.cshtml">
<Generator>RazorGenerator</Generator>
<LastGenOutput>LogInsurance.generated.cs</LastGenOutput>
</None>
<None Include="Views\Job\LogInsuranceError.cshtml">
<Generator>RazorGenerator</Generator>
<LastGenOutput>LogInsuranceError.generated.cs</LastGenOutput>
</None>
<None Include="Views\Job\LogInsuranceDisclose.cshtml">
<Generator>RazorGenerator</Generator>
<LastGenOutput>LogInsuranceDisclose.generated.cs</LastGenOutput>
</None>
<None Include="Views\Job\InsuranceProviderJobDetails.cshtml">
<Generator>RazorGenerator</Generator>
<LastGenOutput>InsuranceProviderJobDetails.generated.cs</LastGenOutput>
</None>
<None Include="Views\Job\RepairProviderJobDetails.cshtml"> <None Include="Views\Job\RepairProviderJobDetails.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>RepairProviderJobDetails.generated.cs</LastGenOutput> <LastGenOutput>RepairProviderJobDetails.generated.cs</LastGenOutput>
@@ -0,0 +1,169 @@
// <auto-generated />
// This file was generated by a T4 template.
// Don't change it directly as your change would get overwritten. Instead, make changes
// to the .tt file (i.e. the T4 template) and save it to regenerate this file.
// Make sure the compiler doesn't complain about missing Xml comments and CLS compliance
// 0108: suppress "Foo hides inherited member Foo. Use the new keyword if hiding was intended." when a controller and its abstract parent are both processed
// 0114: suppress "Foo.BarController.Baz()' hides inherited member 'Qux.BarController.Baz()'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." when an action (with an argument) overrides an action in a parent controller
#pragma warning disable 1591, 3008, 3009, 0108, 0114
#region T4MVC
using System;
using System.Diagnostics;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html;
using System.Web.Routing;
using T4MVC;
namespace Disco.Web.Areas.API.Controllers
{
public partial class EnrollmentController
{
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public EnrollmentController() { }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected EnrollmentController(Dummy d) { }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToAction(ActionResult result)
{
var callInfo = result.GetT4MVCResult();
return RedirectToRoute(callInfo.RouteValueDictionary);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToAction(Task<ActionResult> taskResult)
{
return RedirectToAction(taskResult.Result);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToActionPermanent(ActionResult result)
{
var callInfo = result.GetT4MVCResult();
return RedirectToRoutePermanent(callInfo.RouteValueDictionary);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToActionPermanent(Task<ActionResult> taskResult)
{
return RedirectToActionPermanent(taskResult.Result);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult ResolveSessionPending()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.ResolveSessionPending);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult PendingTimeoutMinutes()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.PendingTimeoutMinutes);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public EnrollmentController Actions { get { return MVC.API.Enrollment; } }
[GeneratedCode("T4MVC", "2.0")]
public readonly string Area = "API";
[GeneratedCode("T4MVC", "2.0")]
public readonly string Name = "Enrollment";
[GeneratedCode("T4MVC", "2.0")]
public const string NameConst = "Enrollment";
[GeneratedCode("T4MVC", "2.0")]
static readonly ActionNamesClass s_actions = new ActionNamesClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionNamesClass ActionNames { get { return s_actions; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionNamesClass
{
public readonly string ResolveSessionPending = "ResolveSessionPending";
public readonly string PendingTimeoutMinutes = "PendingTimeoutMinutes";
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionNameConstants
{
public const string ResolveSessionPending = "ResolveSessionPending";
public const string PendingTimeoutMinutes = "PendingTimeoutMinutes";
}
static readonly ActionParamsClass_ResolveSessionPending s_params_ResolveSessionPending = new ActionParamsClass_ResolveSessionPending();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_ResolveSessionPending ResolveSessionPendingParams { get { return s_params_ResolveSessionPending; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_ResolveSessionPending
{
public readonly string sessionId = "sessionId";
public readonly string approve = "approve";
public readonly string reason = "reason";
}
static readonly ActionParamsClass_PendingTimeoutMinutes s_params_PendingTimeoutMinutes = new ActionParamsClass_PendingTimeoutMinutes();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_PendingTimeoutMinutes PendingTimeoutMinutesParams { get { return s_params_PendingTimeoutMinutes; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_PendingTimeoutMinutes
{
public readonly string PendingTimeoutMinutes = "PendingTimeoutMinutes";
}
static readonly ViewsClass s_views = new ViewsClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ViewsClass Views { get { return s_views; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ViewsClass
{
static readonly _ViewNamesClass s_ViewNames = new _ViewNamesClass();
public _ViewNamesClass ViewNames { get { return s_ViewNames; } }
public class _ViewNamesClass
{
}
}
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public partial class T4MVC_EnrollmentController : Disco.Web.Areas.API.Controllers.EnrollmentController
{
public T4MVC_EnrollmentController() : base(Dummy.Instance) { }
[NonAction]
partial void ResolveSessionPendingOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string sessionId, bool approve, string reason);
[NonAction]
public override System.Web.Mvc.ActionResult ResolveSessionPending(string sessionId, bool approve, string reason)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.ResolveSessionPending);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "sessionId", sessionId);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "approve", approve);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "reason", reason);
ResolveSessionPendingOverride(callInfo, sessionId, approve, reason);
return callInfo;
}
[NonAction]
partial void PendingTimeoutMinutesOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int PendingTimeoutMinutes);
[NonAction]
public override System.Web.Mvc.ActionResult PendingTimeoutMinutes(int PendingTimeoutMinutes)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.PendingTimeoutMinutes);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "PendingTimeoutMinutes", PendingTimeoutMinutes);
PendingTimeoutMinutesOverride(callInfo, PendingTimeoutMinutes);
return callInfo;
}
}
}
#endregion T4MVC
#pragma warning restore 1591, 3008, 3009, 0108, 0114
@@ -103,6 +103,12 @@ namespace Disco.Web.Areas.API.Controllers
} }
[NonAction] [NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult UpdateOnDeviceReadyForReturnExpression()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateOnDeviceReadyForReturnExpression);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult UpdateOnCloseExpression() public virtual System.Web.Mvc.ActionResult UpdateOnCloseExpression()
{ {
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateOnCloseExpression); return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateOnCloseExpression);
@@ -130,6 +136,7 @@ namespace Disco.Web.Areas.API.Controllers
public readonly string UpdateLocationList = "UpdateLocationList"; public readonly string UpdateLocationList = "UpdateLocationList";
public readonly string ImportLocationList = "ImportLocationList"; public readonly string ImportLocationList = "ImportLocationList";
public readonly string UpdateOnCreateExpression = "UpdateOnCreateExpression"; public readonly string UpdateOnCreateExpression = "UpdateOnCreateExpression";
public readonly string UpdateOnDeviceReadyForReturnExpression = "UpdateOnDeviceReadyForReturnExpression";
public readonly string UpdateOnCloseExpression = "UpdateOnCloseExpression"; public readonly string UpdateOnCloseExpression = "UpdateOnCloseExpression";
} }
@@ -143,6 +150,7 @@ namespace Disco.Web.Areas.API.Controllers
public const string UpdateLocationList = "UpdateLocationList"; public const string UpdateLocationList = "UpdateLocationList";
public const string ImportLocationList = "ImportLocationList"; public const string ImportLocationList = "ImportLocationList";
public const string UpdateOnCreateExpression = "UpdateOnCreateExpression"; public const string UpdateOnCreateExpression = "UpdateOnCreateExpression";
public const string UpdateOnDeviceReadyForReturnExpression = "UpdateOnDeviceReadyForReturnExpression";
public const string UpdateOnCloseExpression = "UpdateOnCloseExpression"; public const string UpdateOnCloseExpression = "UpdateOnCloseExpression";
} }
@@ -212,6 +220,15 @@ namespace Disco.Web.Areas.API.Controllers
public readonly string OnCreateExpression = "OnCreateExpression"; public readonly string OnCreateExpression = "OnCreateExpression";
public readonly string redirect = "redirect"; public readonly string redirect = "redirect";
} }
static readonly ActionParamsClass_UpdateOnDeviceReadyForReturnExpression s_params_UpdateOnDeviceReadyForReturnExpression = new ActionParamsClass_UpdateOnDeviceReadyForReturnExpression();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_UpdateOnDeviceReadyForReturnExpression UpdateOnDeviceReadyForReturnExpressionParams { get { return s_params_UpdateOnDeviceReadyForReturnExpression; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_UpdateOnDeviceReadyForReturnExpression
{
public readonly string OnDeviceReadyForReturnExpression = "OnDeviceReadyForReturnExpression";
public readonly string redirect = "redirect";
}
static readonly ActionParamsClass_UpdateOnCloseExpression s_params_UpdateOnCloseExpression = new ActionParamsClass_UpdateOnCloseExpression(); static readonly ActionParamsClass_UpdateOnCloseExpression s_params_UpdateOnCloseExpression = new ActionParamsClass_UpdateOnCloseExpression();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_UpdateOnCloseExpression UpdateOnCloseExpressionParams { get { return s_params_UpdateOnCloseExpression; } } public ActionParamsClass_UpdateOnCloseExpression UpdateOnCloseExpressionParams { get { return s_params_UpdateOnCloseExpression; } }
@@ -333,6 +350,19 @@ namespace Disco.Web.Areas.API.Controllers
return callInfo; return callInfo;
} }
[NonAction]
partial void UpdateOnDeviceReadyForReturnExpressionOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string OnDeviceReadyForReturnExpression, bool redirect);
[NonAction]
public override System.Web.Mvc.ActionResult UpdateOnDeviceReadyForReturnExpression(string OnDeviceReadyForReturnExpression, bool redirect)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateOnDeviceReadyForReturnExpression);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "OnDeviceReadyForReturnExpression", OnDeviceReadyForReturnExpression);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "redirect", redirect);
UpdateOnDeviceReadyForReturnExpressionOverride(callInfo, OnDeviceReadyForReturnExpression, redirect);
return callInfo;
}
[NonAction] [NonAction]
partial void UpdateOnCloseExpressionOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string OnCloseExpression, bool redirect); partial void UpdateOnCloseExpressionOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string OnCloseExpression, bool redirect);
@@ -59,6 +59,12 @@ namespace Disco.Web.Areas.API.Controllers
return RedirectToActionPermanent(taskResult.Result); return RedirectToActionPermanent(taskResult.Result);
} }
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult LicenseCheck()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.LicenseCheck);
}
[NonAction] [NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult UpdateOrganisationName() public virtual System.Web.Mvc.ActionResult UpdateOrganisationName()
@@ -162,6 +168,7 @@ namespace Disco.Web.Areas.API.Controllers
public readonly string UpdateLastNetworkLogonDates = "UpdateLastNetworkLogonDates"; public readonly string UpdateLastNetworkLogonDates = "UpdateLastNetworkLogonDates";
public readonly string UpdateAttachmentThumbnails = "UpdateAttachmentThumbnails"; public readonly string UpdateAttachmentThumbnails = "UpdateAttachmentThumbnails";
public readonly string UpdateADDeviceDescriptions = "UpdateADDeviceDescriptions"; public readonly string UpdateADDeviceDescriptions = "UpdateADDeviceDescriptions";
public readonly string LicenseCheck = "LicenseCheck";
public readonly string UpdateCheck = "UpdateCheck"; public readonly string UpdateCheck = "UpdateCheck";
public readonly string UpdateOrganisationName = "UpdateOrganisationName"; public readonly string UpdateOrganisationName = "UpdateOrganisationName";
public readonly string OrganisationLogo = "OrganisationLogo"; public readonly string OrganisationLogo = "OrganisationLogo";
@@ -187,6 +194,7 @@ namespace Disco.Web.Areas.API.Controllers
public const string UpdateLastNetworkLogonDates = "UpdateLastNetworkLogonDates"; public const string UpdateLastNetworkLogonDates = "UpdateLastNetworkLogonDates";
public const string UpdateAttachmentThumbnails = "UpdateAttachmentThumbnails"; public const string UpdateAttachmentThumbnails = "UpdateAttachmentThumbnails";
public const string UpdateADDeviceDescriptions = "UpdateADDeviceDescriptions"; public const string UpdateADDeviceDescriptions = "UpdateADDeviceDescriptions";
public const string LicenseCheck = "LicenseCheck";
public const string UpdateCheck = "UpdateCheck"; public const string UpdateCheck = "UpdateCheck";
public const string UpdateOrganisationName = "UpdateOrganisationName"; public const string UpdateOrganisationName = "UpdateOrganisationName";
public const string OrganisationLogo = "OrganisationLogo"; public const string OrganisationLogo = "OrganisationLogo";
@@ -207,6 +215,14 @@ namespace Disco.Web.Areas.API.Controllers
} }
static readonly ActionParamsClass_LicenseCheck s_params_LicenseCheck = new ActionParamsClass_LicenseCheck();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_LicenseCheck LicenseCheckParams { get { return s_params_LicenseCheck; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_LicenseCheck
{
public readonly string license = "license";
}
static readonly ActionParamsClass_UpdateOrganisationName s_params_UpdateOrganisationName = new ActionParamsClass_UpdateOrganisationName(); static readonly ActionParamsClass_UpdateOrganisationName s_params_UpdateOrganisationName = new ActionParamsClass_UpdateOrganisationName();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_UpdateOrganisationName UpdateOrganisationNameParams { get { return s_params_UpdateOrganisationName; } } public ActionParamsClass_UpdateOrganisationName UpdateOrganisationNameParams { get { return s_params_UpdateOrganisationName; } }
@@ -404,6 +420,18 @@ namespace Disco.Web.Areas.API.Controllers
return callInfo; return callInfo;
} }
[NonAction]
partial void LicenseCheckOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string license);
[NonAction]
public override System.Web.Mvc.ActionResult LicenseCheck(string license)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.LicenseCheck);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "license", license);
LicenseCheckOverride(callInfo, license);
return callInfo;
}
[NonAction] [NonAction]
partial void UpdateCheckOverride(T4MVC_System_Web_Mvc_ActionResult callInfo); partial void UpdateCheckOverride(T4MVC_System_Web_Mvc_ActionResult callInfo);
@@ -101,6 +101,18 @@ namespace Disco.Web.Controllers
{ {
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.RepairProviderJobDetails); return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.RepairProviderJobDetails);
} }
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult LogInsurance()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.LogInsurance);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult InsuranceProviderJobDetails()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.InsuranceProviderJobDetails);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public JobController Actions { get { return MVC.Job; } } public JobController Actions { get { return MVC.Job; } }
@@ -139,6 +151,8 @@ namespace Disco.Web.Controllers
public readonly string WarrantyProviderJobDetails = "WarrantyProviderJobDetails"; public readonly string WarrantyProviderJobDetails = "WarrantyProviderJobDetails";
public readonly string LogRepair = "LogRepair"; public readonly string LogRepair = "LogRepair";
public readonly string RepairProviderJobDetails = "RepairProviderJobDetails"; public readonly string RepairProviderJobDetails = "RepairProviderJobDetails";
public readonly string LogInsurance = "LogInsurance";
public readonly string InsuranceProviderJobDetails = "InsuranceProviderJobDetails";
} }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
@@ -166,6 +180,8 @@ namespace Disco.Web.Controllers
public const string WarrantyProviderJobDetails = "WarrantyProviderJobDetails"; public const string WarrantyProviderJobDetails = "WarrantyProviderJobDetails";
public const string LogRepair = "LogRepair"; public const string LogRepair = "LogRepair";
public const string RepairProviderJobDetails = "RepairProviderJobDetails"; public const string RepairProviderJobDetails = "RepairProviderJobDetails";
public const string LogInsurance = "LogInsurance";
public const string InsuranceProviderJobDetails = "InsuranceProviderJobDetails";
} }
@@ -235,6 +251,26 @@ namespace Disco.Web.Controllers
{ {
public readonly string id = "id"; public readonly string id = "id";
} }
static readonly ActionParamsClass_LogInsurance s_params_LogInsurance = new ActionParamsClass_LogInsurance();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_LogInsurance LogInsuranceParams { get { return s_params_LogInsurance; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_LogInsurance
{
public readonly string id = "id";
public readonly string providerId = "providerId";
public readonly string organisationAddressId = "organisationAddressId";
public readonly string m = "m";
public readonly string form = "form";
}
static readonly ActionParamsClass_InsuranceProviderJobDetails s_params_InsuranceProviderJobDetails = new ActionParamsClass_InsuranceProviderJobDetails();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_InsuranceProviderJobDetails InsuranceProviderJobDetailsParams { get { return s_params_InsuranceProviderJobDetails; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_InsuranceProviderJobDetails
{
public readonly string id = "id";
}
static readonly ViewsClass s_views = new ViewsClass(); static readonly ViewsClass s_views = new ViewsClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ViewsClass Views { get { return s_views; } } public ViewsClass Views { get { return s_views; } }
@@ -250,7 +286,11 @@ namespace Disco.Web.Controllers
public readonly string Create = "Create"; public readonly string Create = "Create";
public readonly string Create_Redirect = "Create_Redirect"; public readonly string Create_Redirect = "Create_Redirect";
public readonly string Index = "Index"; public readonly string Index = "Index";
public readonly string InsuranceProviderJobDetails = "InsuranceProviderJobDetails";
public readonly string List = "List"; public readonly string List = "List";
public readonly string LogInsurance = "LogInsurance";
public readonly string LogInsuranceDisclose = "LogInsuranceDisclose";
public readonly string LogInsuranceError = "LogInsuranceError";
public readonly string LogRepair = "LogRepair"; public readonly string LogRepair = "LogRepair";
public readonly string LogRepairDisclose = "LogRepairDisclose"; public readonly string LogRepairDisclose = "LogRepairDisclose";
public readonly string LogRepairError = "LogRepairError"; public readonly string LogRepairError = "LogRepairError";
@@ -266,7 +306,11 @@ namespace Disco.Web.Controllers
public readonly string Create = "~/Views/Job/Create.cshtml"; public readonly string Create = "~/Views/Job/Create.cshtml";
public readonly string Create_Redirect = "~/Views/Job/Create_Redirect.cshtml"; public readonly string Create_Redirect = "~/Views/Job/Create_Redirect.cshtml";
public readonly string Index = "~/Views/Job/Index.cshtml"; public readonly string Index = "~/Views/Job/Index.cshtml";
public readonly string InsuranceProviderJobDetails = "~/Views/Job/InsuranceProviderJobDetails.cshtml";
public readonly string List = "~/Views/Job/List.cshtml"; public readonly string List = "~/Views/Job/List.cshtml";
public readonly string LogInsurance = "~/Views/Job/LogInsurance.cshtml";
public readonly string LogInsuranceDisclose = "~/Views/Job/LogInsuranceDisclose.cshtml";
public readonly string LogInsuranceError = "~/Views/Job/LogInsuranceError.cshtml";
public readonly string LogRepair = "~/Views/Job/LogRepair.cshtml"; public readonly string LogRepair = "~/Views/Job/LogRepair.cshtml";
public readonly string LogRepairDisclose = "~/Views/Job/LogRepairDisclose.cshtml"; public readonly string LogRepairDisclose = "~/Views/Job/LogRepairDisclose.cshtml";
public readonly string LogRepairError = "~/Views/Job/LogRepairError.cshtml"; public readonly string LogRepairError = "~/Views/Job/LogRepairError.cshtml";
@@ -609,6 +653,45 @@ namespace Disco.Web.Controllers
return callInfo; return callInfo;
} }
[NonAction]
partial void LogInsuranceOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, string providerId, int? organisationAddressId);
[NonAction]
public override System.Web.Mvc.ActionResult LogInsurance(int id, string providerId, int? organisationAddressId)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.LogInsurance);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "providerId", providerId);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "organisationAddressId", organisationAddressId);
LogInsuranceOverride(callInfo, id, providerId, organisationAddressId);
return callInfo;
}
[NonAction]
partial void LogInsuranceOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, Disco.Web.Models.Job.LogInsuranceModel m, System.Web.Mvc.FormCollection form);
[NonAction]
public override System.Web.Mvc.ActionResult LogInsurance(Disco.Web.Models.Job.LogInsuranceModel m, System.Web.Mvc.FormCollection form)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.LogInsurance);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "m", m);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "form", form);
LogInsuranceOverride(callInfo, m, form);
return callInfo;
}
[NonAction]
partial void InsuranceProviderJobDetailsOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id);
[NonAction]
public override System.Web.Mvc.ActionResult InsuranceProviderJobDetails(int id)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.InsuranceProviderJobDetails);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id);
InsuranceProviderJobDetailsOverride(callInfo, id);
return callInfo;
}
} }
} }
+1
View File
@@ -62,6 +62,7 @@ namespace T4MVC
public Disco.Web.Areas.API.Controllers.DeviceProfileController DeviceProfile = new Disco.Web.Areas.API.Controllers.T4MVC_DeviceProfileController(); public Disco.Web.Areas.API.Controllers.DeviceProfileController DeviceProfile = new Disco.Web.Areas.API.Controllers.T4MVC_DeviceProfileController();
public Disco.Web.Areas.API.Controllers.DocumentTemplateController DocumentTemplate = new Disco.Web.Areas.API.Controllers.T4MVC_DocumentTemplateController(); public Disco.Web.Areas.API.Controllers.DocumentTemplateController DocumentTemplate = new Disco.Web.Areas.API.Controllers.T4MVC_DocumentTemplateController();
public Disco.Web.Areas.API.Controllers.DocumentTemplatePackageController DocumentTemplatePackage = new Disco.Web.Areas.API.Controllers.T4MVC_DocumentTemplatePackageController(); public Disco.Web.Areas.API.Controllers.DocumentTemplatePackageController DocumentTemplatePackage = new Disco.Web.Areas.API.Controllers.T4MVC_DocumentTemplatePackageController();
public Disco.Web.Areas.API.Controllers.EnrollmentController Enrollment = new Disco.Web.Areas.API.Controllers.T4MVC_EnrollmentController();
public Disco.Web.Areas.API.Controllers.ExpressionsController Expressions = new Disco.Web.Areas.API.Controllers.T4MVC_ExpressionsController(); public Disco.Web.Areas.API.Controllers.ExpressionsController Expressions = new Disco.Web.Areas.API.Controllers.T4MVC_ExpressionsController();
public Disco.Web.Areas.API.Controllers.JobController Job = new Disco.Web.Areas.API.Controllers.T4MVC_JobController(); public Disco.Web.Areas.API.Controllers.JobController Job = new Disco.Web.Areas.API.Controllers.T4MVC_JobController();
public Disco.Web.Areas.API.Controllers.JobPreferencesController JobPreferences = new Disco.Web.Areas.API.Controllers.T4MVC_JobPreferencesController(); public Disco.Web.Areas.API.Controllers.JobPreferencesController JobPreferences = new Disco.Web.Areas.API.Controllers.T4MVC_JobPreferencesController();
+3 -1
View File
@@ -1,4 +1,5 @@
using Disco.Models.Services.Job.Statistics; using Disco.Models.ClientServices;
using Disco.Models.Services.Job.Statistics;
using Disco.Models.Services.Jobs.JobLists; using Disco.Models.Services.Jobs.JobLists;
using Disco.Models.UI.Job; using Disco.Models.UI.Job;
using System.Collections.Generic; using System.Collections.Generic;
@@ -9,6 +10,7 @@ namespace Disco.Web.Models.Job
{ {
public JobTableModel MyJobs { get; set; } public JobTableModel MyJobs { get; set; }
public JobTableModel StaleJobs { get; set; } public JobTableModel StaleJobs { get; set; }
public List<EnrolResponse> PendingEnrollments { get; set; }
public List<DailyOpenedClosedItem> DailyOpenedClosedStatistics { get; set; } public List<DailyOpenedClosedItem> DailyOpenedClosedStatistics { get; set; }
} }
+125
View File
@@ -0,0 +1,125 @@
using Disco.Data.Repository;
using Disco.Services.Plugins;
using Disco.Services.Plugins.Features.InsuranceProvider;
using Disco.Services.Users;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Data.Entity;
namespace Disco.Web.Models.Job
{
public class LogInsuranceModel
{
public Disco.Models.Repository.Job Job { get; set; }
public List<PluginFeatureManifest> Providers { get; set; }
public PluginFeatureManifest Provider { get; set; }
public List<Disco.Models.BI.Config.OrganisationAddress> OrganisationAddresses { get; set; }
public Disco.Models.BI.Config.OrganisationAddress OrganisationAddress { get; set; }
public List<Disco.Models.Repository.JobAttachment> Attachments { get; set; }
public Disco.Models.Repository.User TechUser { get; set; }
[Required]
public int JobId { get; set; }
[Required(ErrorMessage = "Please specify a Address")]
public int? OrganisationAddressId { get; set; }
[Required(ErrorMessage = "Please specify a Provider")]
public string ProviderId { get; set; }
public List<int> AttachmentIds { get; set; }
[Required]
public string SubmissionAction { get; set; }
public bool IsManualProvider =>
ProviderId == "MANUAL";
public string ManualProviderName { get; set; }
public string ManualProviderReference { get; set; }
public Tuple<Type, object> ProviderSubmitJobBeginResult { get; set; }
public string ProviderPropertiesJson { get; set; }
public Dictionary<string, string> ProviderProperties()
{
var p = default(Dictionary<string, string>);
if (!string.IsNullOrEmpty(ProviderPropertiesJson))
{
try
{
p = JsonConvert.DeserializeObject<Dictionary<string, string>>(ProviderPropertiesJson);
}
catch (Exception)
{
// Ignore Errors
}
}
return p;
}
public Dictionary<string, string> DiscloseProperties { get; set; }
public Exception Error { get; set; }
public void UpdateModel(DiscoDataContext Database, bool IsPostBack)
{
Database.Configuration.LazyLoadingEnabled = true;
if (Job == null)
{
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 = Database.Jobs
.Include(j => j.Device.DeviceModel)
.Include(j => j.JobMetaNonWarranty)
.Include(j => j.JobMetaInsurance)
.Include(j => j.JobSubTypes)
.Include(j => j.JobAttachments)
.Where(j => j.Id == JobId)
.FirstOrDefault();
if (Job == null)
throw new ArgumentException("Invalid Job Number Specified", "JobId");
}
TechUser = UserService.GetUser(UserService.CurrentUserId, Database, true);
Providers = Plugins.GetPluginFeatures(typeof(InsuranceProviderFeature));
if (!IsPostBack && string.IsNullOrEmpty(ProviderId))
ProviderId = "MANUAL";
if (!string.IsNullOrEmpty(ProviderId) && ProviderId != "MANUAL")
Provider = Plugins.GetPluginFeature(ProviderId, typeof(InsuranceProviderFeature));
OrganisationAddresses = Database.DiscoConfiguration.OrganisationAddresses.Addresses.OrderBy(a => a.Name).ToList();
if (!IsPostBack && !OrganisationAddressId.HasValue)
{
OrganisationAddressId = Job.Device.DeviceProfile.DefaultOrganisationAddress;
if (!OrganisationAddressId.HasValue && OrganisationAddresses.Count == 1)
OrganisationAddressId = OrganisationAddresses[0].Id;
}
if (OrganisationAddressId.HasValue)
OrganisationAddress = OrganisationAddresses.FirstOrDefault(oa => oa.Id == OrganisationAddressId.Value);
if (AttachmentIds == null)
{
AttachmentIds = new List<int>();
Attachments = new List<Disco.Models.Repository.JobAttachment>();
}
else
{
Attachments = Job.JobAttachments.Where(ja => AttachmentIds.Contains(ja.Id)).ToList();
}
}
}
}
+8 -1
View File
@@ -6,6 +6,7 @@ using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq; using System.Linq;
namespace Disco.Web.Models.Job namespace Disco.Web.Models.Job
@@ -84,7 +85,11 @@ namespace Disco.Web.Models.Job
catch (Exception) { } catch (Exception) { }
} }
Job = Database.Jobs.Include("Device.DeviceModel").Include("JobMetaWarranty").Include("JobSubTypes").Include("JobAttachments") Job = Database.Jobs
.Include(j => j.Device.DeviceModel)
.Include(j => j.JobMetaNonWarranty)
.Include(j => j.JobSubTypes)
.Include(j => j.JobAttachments)
.Where(j => j.Id == JobId) .Where(j => j.Id == JobId)
.FirstOrDefault(); .FirstOrDefault();
@@ -113,6 +118,8 @@ namespace Disco.Web.Models.Job
if (!IsPostBack && !this.OrganisationAddressId.HasValue) if (!IsPostBack && !this.OrganisationAddressId.HasValue)
{ {
OrganisationAddressId = Job.Device.DeviceProfile.DefaultOrganisationAddress; OrganisationAddressId = Job.Device.DeviceProfile.DefaultOrganisationAddress;
if (!OrganisationAddressId.HasValue && OrganisationAddresses.Count == 1)
OrganisationAddressId = OrganisationAddresses[0].Id;
} }
if (this.OrganisationAddressId.HasValue) if (this.OrganisationAddressId.HasValue)
this.OrganisationAddress = this.OrganisationAddresses.FirstOrDefault(oa => oa.Id == this.OrganisationAddressId.Value); this.OrganisationAddress = this.OrganisationAddresses.FirstOrDefault(oa => oa.Id == this.OrganisationAddressId.Value);
+8 -1
View File
@@ -6,6 +6,7 @@ using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq; using System.Linq;
namespace Disco.Web.Models.Job namespace Disco.Web.Models.Job
@@ -84,7 +85,11 @@ namespace Disco.Web.Models.Job
} catch (Exception) {} } catch (Exception) {}
} }
Job = Database.Jobs.Include("Device.DeviceModel").Include("JobMetaWarranty").Include("JobSubTypes").Include("JobAttachments") Job = Database.Jobs
.Include(j => j.Device.DeviceModel)
.Include(j => j.JobMetaWarranty)
.Include(j => j.JobSubTypes)
.Include(j => j.JobAttachments)
.Where(j => j.Id == JobId) .Where(j => j.Id == JobId)
.FirstOrDefault(); .FirstOrDefault();
@@ -113,6 +118,8 @@ namespace Disco.Web.Models.Job
if (!IsPostBack && !this.OrganisationAddressId.HasValue) if (!IsPostBack && !this.OrganisationAddressId.HasValue)
{ {
OrganisationAddressId = Job.Device.DeviceProfile.DefaultOrganisationAddress; OrganisationAddressId = Job.Device.DeviceProfile.DefaultOrganisationAddress;
if (!OrganisationAddressId.HasValue && OrganisationAddresses.Count == 1)
OrganisationAddressId = OrganisationAddresses[0].Id;
} }
if (this.OrganisationAddressId.HasValue) if (this.OrganisationAddressId.HasValue)
this.OrganisationAddress = this.OrganisationAddresses.FirstOrDefault(oa => oa.Id == this.OrganisationAddressId.Value); this.OrganisationAddress = this.OrganisationAddresses.FirstOrDefault(oa => oa.Id == this.OrganisationAddressId.Value);
+2 -2
View File
@@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
// //
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("2.3.23161.0650")] [assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.3.23161.0650")] [assembly: AssemblyFileVersion("2.4.24270.0000")]
+17 -1
View File
@@ -22,7 +22,7 @@
<div id="chartHostJobDailyOpenedClosed" style="height: 175px;"> <div id="chartHostJobDailyOpenedClosed" style="height: 175px;">
</div> </div>
@{ @{
var jsonData = new HtmlString(Json.Encode(Model.DailyOpenedClosedStatistics)); var jsonData = new HtmlString(Json.Encode(Model.DailyOpenedClosedStatistics));
} }
<script type="text/javascript"> <script type="text/javascript">
(function () { (function () {
@@ -144,4 +144,20 @@
<h2>Stale Jobs (@Model.StaleJobs.Items.Count())</h2> <h2>Stale Jobs (@Model.StaleJobs.Items.Count())</h2>
@Html.Partial(MVC.Shared.Views._JobTable, Model.StaleJobs, new ViewDataDictionary()) @Html.Partial(MVC.Shared.Views._JobTable, Model.StaleJobs, new ViewDataDictionary())
</div> </div>
}
@if (Model.PendingEnrollments != null && Model.PendingEnrollments.Count > 0 && Authorization.Has(Claims.Device.Actions.EnrolDevices))
{
<div id="pendingEnrollments">
<i class="fa fa-exclamation-circle info"></i>
<div>There are device enrollments pending approval.</div>
<a href="@Url.Action(MVC.Config.Enrolment.Status())" class="button small alert" target="_blank">View Enrollments</a>
</div>
<script>
$(function () {
var layout_PageHeading = $('#layout_PageHeading').height(80);
$('#pendingEnrollments')
.detach()
.appendTo(layout_PageHeading);
});
</script>
} }
+76 -29
View File
@@ -131,7 +131,7 @@ WriteLiteral(">\r\n </div>\r\n");
#line 24 "..\..\Views\Job\Index.cshtml" #line 24 "..\..\Views\Job\Index.cshtml"
var jsonData = new HtmlString(Json.Encode(Model.DailyOpenedClosedStatistics)); var jsonData = new HtmlString(Json.Encode(Model.DailyOpenedClosedStatistics));
#line default #line default
@@ -174,34 +174,34 @@ WriteLiteral(">\r\n (function () {\r\n var cha
"top\',\r\n y: 0,\r\n " + "top\',\r\n y: 0,\r\n " +
" floating: true,\r\n borderWidth: 0,\r\n " + " floating: true,\r\n borderWidth: 0,\r\n " +
" itemStyle: {\r\n " + " itemStyle: {\r\n " +
" color: \'#333\',\n fontWeight: \'normal" + " color: \'#333\',\r\n fontWeight: \'norma" +
"\'\r\n }\r\n },\r\n " + "l\'\r\n }\r\n },\r\n " +
" xAxis: {\r\n type" + " xAxis: {\r\n typ" +
": \'datetime\',\r\n tickInterval: 7 * 24 * 3600 *" + "e: \'datetime\',\r\n tickInterval: 7 * 24 * 3600 " +
" 1000, // week\r\n tickWidth: 1,\r\n " + "* 1000, // week\r\n tickWidth: 1,\r\n " +
" gridLineWidth: 1,\r\n da" + " gridLineWidth: 1,\r\n d" +
"teTimeLabelFormats: {\r\n week: \'%e %b\'\r\n " + "ateTimeLabelFormats: {\r\n week: \'%e %b\'\r\n " +
" }\r\n },\r\n " + " }\r\n },\r\n " +
" yAxis: [{\r\n title: {" + " yAxis: [{\r\n title: " +
"\r\n text: null\r\n " + "{\r\n text: null\r\n " +
" },\r\n labels: {\r\n " + " },\r\n labels: {\r\n " +
" enabled: false\r\n },\r\n " + " enabled: false\r\n },\r\n " +
" min: 0\r\n }, {\r\n " + " min: 0\r\n }, {\r\n" +
" title: {\r\n " + " title: {\r\n " +
" text: null\r\n },\r\n " + " text: null\r\n },\r\n " +
" labels: {\r\n enabled: false\r\n" + " labels: {\r\n enabled: false\r" +
" },\r\n min:" + "\n },\r\n min" +
" 0\r\n }],\r\n series:" + ": 0\r\n }],\r\n series" +
" [{\r\n name: \'Total Open Jobs\',\r\n " + ": [{\r\n name: \'Total Open Jobs\',\r\n " +
" data: dataTotalOpenJobs,\r\n " + " data: dataTotalOpenJobs,\r\n " +
" yAxis: 1\r\n }, {\r\n " + " yAxis: 1\r\n }, {\r\n " +
" name: \'Closed Jobs\',\r\n data: dataClo" + " name: \'Closed Jobs\',\r\n data: dataCl" +
"sedJobs\r\n }, {\r\n " + "osedJobs\r\n }, {\r\n " +
" name: \'Opened Jobs\',\r\n data: dataOpenedJob" + " name: \'Opened Jobs\',\r\n data: dataOpenedJo" +
"s\r\n }],\r\n credits:" + "bs\r\n }],\r\n credits" +
" {\r\n enabled: false\r\n " + ": {\r\n enabled: false\r\n " +
" }\r\n });\r\n });\r\n " + " }\r\n });\r\n });\r\n " +
" }\r\n chartData = $.parseJSON(\'"); " }\r\n chartData = $.parseJSON(\'");
#line 126 "..\..\Views\Job\Index.cshtml" #line 126 "..\..\Views\Job\Index.cshtml"
@@ -300,6 +300,53 @@ WriteLiteral("\r\n </div>\r\n");
#line 147 "..\..\Views\Job\Index.cshtml" #line 147 "..\..\Views\Job\Index.cshtml"
} }
#line default
#line hidden
#line 148 "..\..\Views\Job\Index.cshtml"
if (Model.PendingEnrollments != null && Model.PendingEnrollments.Count > 0 && Authorization.Has(Claims.Device.Actions.EnrolDevices))
{
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" id=\"pendingEnrollments\"");
WriteLiteral(">\r\n <i");
WriteLiteral(" class=\"fa fa-exclamation-circle info\"");
WriteLiteral("></i>\r\n <div>There are device enrollments pending approval.</div>\r\n " +
" <a");
WriteAttribute("href", Tuple.Create(" href=\"", 6766), Tuple.Create("\"", 6815)
#line 153 "..\..\Views\Job\Index.cshtml"
, Tuple.Create(Tuple.Create("", 6773), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.Config.Enrolment.Status())
#line default
#line hidden
, 6773), false)
);
WriteLiteral(" class=\"button small alert\"");
WriteLiteral(" target=\"_blank\"");
WriteLiteral(">View Enrollments</a>\r\n </div>\r\n");
WriteLiteral(" <script>\r\n $(function () {\r\n var layout_PageHeading = $(\'#l" +
"ayout_PageHeading\').height(80);\r\n $(\'#pendingEnrollments\')\r\n " +
" .detach()\r\n .appendTo(layout_PageHeading);\r\n });\r\n " +
" </script>\r\n");
#line 163 "..\..\Views\Job\Index.cshtml"
}
#line default #line default
#line hidden #line hidden
@@ -0,0 +1,55 @@
@model Disco.Web.Models.Job.ProviderJobDetailsModel
@{ Layout = null;
Authorization.Require(Claims.Job.Properties.NonWarrantyProperties.InsuranceDetails);
if (Model.JobDetailsException != null)
{
<h3>
Error:</h3>
<div>
<strong>@Model.JobDetailsException.Message</strong>
</div>
<a href="#" id="errorShow" class="smallMessage">(show more)</a>
<div id="errorMore" style="display: none">
<br />
<strong>Error Type: </strong>@Model.JobDetailsException.GetType().Name
<br />
<strong>Stack Trace:</strong>
<div class="code">
@Model.JobDetailsException.StackTrace.ToMultilineString()
</div>
@if (Model.JobDetailsException.InnerException != null)
{
<hr />
<div>
<strong>Inner Exception:</strong> @Model.JobDetailsException.InnerException.Message<br />
<strong>Error Type:</strong> @Model.JobDetailsException.GetType().Name<br />
<strong>Stack Trace:</strong>
<div class="code">
@Model.JobDetailsException.InnerException.StackTrace
</div>
</div>
}
<script type="text/javascript">
$(function () {
$('#errorShow').click(function () {
$(this).hide();
$('#errorMore').slideDown();
});
});
</script>
</div>
}
else
{
if (Model.JobDetailsSupported)
{
@Html.PartialCompiled(Model.ViewType, Model.ViewModel)
}
else
{
<span class="smallMessage">@Model.JobDetailsNotSupportedMessage</span>
}
}
}
@@ -0,0 +1,236 @@
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Disco.Web.Views.Job
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Web.Security;
using System.Web.UI;
using System.Web.WebPages;
using Disco;
using Disco.Models.Repository;
using Disco.Services;
using Disco.Services.Authorization;
using Disco.Services.Web;
using Disco.Web;
using Disco.Web.Extensions;
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")]
[System.Web.WebPages.PageVirtualPathAttribute("~/Views/Job/InsuranceProviderJobDetails.cshtml")]
public partial class InsuranceProviderJobDetails : Disco.Services.Web.WebViewPage<Disco.Web.Models.Job.ProviderJobDetailsModel>
{
public InsuranceProviderJobDetails()
{
}
public override void Execute()
{
#line 2 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
Layout = null;
Authorization.Require(Claims.Job.Properties.NonWarrantyProperties.InsuranceDetails);
if (Model.JobDetailsException != null)
{
#line default
#line hidden
WriteLiteral(" <h3>\r\n Error:</h3>\r\n");
WriteLiteral(" <div>\r\n <strong>");
#line 11 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
Write(Model.JobDetailsException.Message);
#line default
#line hidden
WriteLiteral("</strong>\r\n </div>\r\n");
WriteLiteral(" <a");
WriteLiteral(" href=\"#\"");
WriteLiteral(" id=\"errorShow\"");
WriteLiteral(" class=\"smallMessage\"");
WriteLiteral(">(show more)</a>\r\n");
WriteLiteral(" <div");
WriteLiteral(" id=\"errorMore\"");
WriteLiteral(" style=\"display: none\"");
WriteLiteral(">\r\n <br />\r\n <strong>Error Type: </strong>");
#line 16 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
Write(Model.JobDetailsException.GetType().Name);
#line default
#line hidden
WriteLiteral("\r\n <br />\r\n <strong>Stack Trace:</strong>\r\n <div");
WriteLiteral(" class=\"code\"");
WriteLiteral(">\r\n");
WriteLiteral(" ");
#line 20 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
Write(Model.JobDetailsException.StackTrace.ToMultilineString());
#line default
#line hidden
WriteLiteral("\r\n </div>\r\n");
#line 22 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
#line default
#line hidden
#line 22 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
if (Model.JobDetailsException.InnerException != null)
{
#line default
#line hidden
WriteLiteral(" <hr />\r\n");
WriteLiteral(" <div>\r\n <strong>Inner Exception:</strong> ");
#line 26 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
Write(Model.JobDetailsException.InnerException.Message);
#line default
#line hidden
WriteLiteral("<br />\r\n <strong>Error Type:</strong> ");
#line 27 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
Write(Model.JobDetailsException.GetType().Name);
#line default
#line hidden
WriteLiteral("<br />\r\n <strong>Stack Trace:</strong>\r\n <div");
WriteLiteral(" class=\"code\"");
WriteLiteral(">\r\n");
WriteLiteral(" ");
#line 30 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
Write(Model.JobDetailsException.InnerException.StackTrace);
#line default
#line hidden
WriteLiteral("\r\n </div>\r\n </div>\r\n");
#line 33 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
}
#line default
#line hidden
WriteLiteral(" <script");
WriteLiteral(" type=\"text/javascript\"");
WriteLiteral(">\r\n $(function () {\r\n $(\'#errorShow\').click(function ()" +
" {\r\n $(this).hide();\r\n $(\'#errorMore\').sli" +
"deDown();\r\n });\r\n });\r\n </script>\r\n </div>\r\n" +
"");
#line 43 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
}
else
{
if (Model.JobDetailsSupported)
{
#line default
#line hidden
#line 48 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
Write(Html.PartialCompiled(Model.ViewType, Model.ViewModel));
#line default
#line hidden
#line 48 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <span");
WriteLiteral(" class=\"smallMessage\"");
WriteLiteral(">");
#line 52 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
Write(Model.JobDetailsNotSupportedMessage);
#line default
#line hidden
WriteLiteral("</span>\r\n");
#line 53 "..\..\Views\Job\InsuranceProviderJobDetails.cshtml"
}
}
#line default
#line hidden
WriteLiteral("\r\n");
}
}
}
#pragma warning restore 1591
+449 -357
View File
@@ -8,13 +8,14 @@
if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.InsuranceDetails)) if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.InsuranceDetails))
{ {
Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers"); Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers");
<tr> <tr>
<th style="width: 230px;">Date of Loss or Damage <th style="width: 230px;">
</th> Date of Loss or Damage
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.LossOrDamageDate) <td>
@AjaxHelpers.AjaxLoader() @Html.EditorFor(m => m.Job.JobMetaInsurance.LossOrDamageDate)
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
var dateField = $('#Job_JobMetaInsurance_LossOrDamageDate'); var dateField = $('#Job_JobMetaInsurance_LossOrDamageDate');
document.DiscoFunctions.DateChangeHelper( document.DiscoFunctions.DateChangeHelper(
@@ -25,17 +26,18 @@
null null
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Event Location <th>
</th> Event Location
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.EventLocation) <td>
@AjaxHelpers.AjaxSave() @Html.EditorFor(m => m.Job.JobMetaInsurance.EventLocation)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
$('#Job_JobMetaInsurance_EventLocation'), $('#Job_JobMetaInsurance_EventLocation'),
@@ -44,17 +46,18 @@
'EventLocation' 'EventLocation'
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Description <th>
</th> Description
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.Description) <td>
@AjaxHelpers.AjaxSave() @Html.EditorFor(m => m.Job.JobMetaInsurance.Description)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
$('#Job_JobMetaInsurance_Description'), $('#Job_JobMetaInsurance_Description'),
@@ -63,31 +66,32 @@
'Description' 'Description'
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
<tr> <tr>
<th style="width: 200px;">&nbsp; <th style="width: 200px;">
</th> &nbsp;
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.ThirdPartyCaused)@Html.LabelFor(m => m.Job.JobMetaInsurance.ThirdPartyCaused) <td>
@AjaxHelpers.AjaxSave() @Html.EditorFor(m => m.Job.JobMetaInsurance.ThirdPartyCaused)@Html.LabelFor(m => m.Job.JobMetaInsurance.ThirdPartyCaused)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
<div id="Job_JobMetaInsurance_ThirdPartyCaused_Details" style="padding-left: 25px;"> @AjaxHelpers.AjaxLoader()
<div> <div id="Job_JobMetaInsurance_ThirdPartyCaused_Details" style="padding-left: 25px;">
<h5>Third Party Name</h5> <div>
@Html.EditorFor(m => m.Job.JobMetaInsurance.ThirdPartyCausedName) <h5>Third Party Name</h5>
@AjaxHelpers.AjaxSave() @Html.EditorFor(m => m.Job.JobMetaInsurance.ThirdPartyCausedName)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
</div>
<div>
<h5>Why Third Parties Fault</h5>
@Html.EditorFor(m => m.Job.JobMetaInsurance.ThirdPartyCausedWhy)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
</div>
</div> </div>
<div> <script type="text/javascript">
<h5>Why Third Parties Fault</h5>
@Html.EditorFor(m => m.Job.JobMetaInsurance.ThirdPartyCausedWhy)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
</div>
</div>
<script type="text/javascript">
$(function () { $(function () {
var thirdPartyField = $('#Job_JobMetaInsurance_ThirdPartyCaused'); var thirdPartyField = $('#Job_JobMetaInsurance_ThirdPartyCaused');
var thirdPartyDetails = $('#Job_JobMetaInsurance_ThirdPartyCaused_Details'); var thirdPartyDetails = $('#Job_JobMetaInsurance_ThirdPartyCaused_Details');
@@ -128,17 +132,18 @@
'ThirdPartyCausedWhy' 'ThirdPartyCausedWhy'
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Witnessed by (Name/Address) <th>
</th> Witnessed by (Name/Address)
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.WitnessesNamesAddresses) <td>
@AjaxHelpers.AjaxSave() @Html.EditorFor(m => m.Job.JobMetaInsurance.WitnessesNamesAddresses)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
$('#Job_JobMetaInsurance_WitnessesNamesAddresses'), $('#Job_JobMetaInsurance_WitnessesNamesAddresses'),
@@ -147,17 +152,18 @@
'WitnessesNamesAddresses' 'WitnessesNamesAddresses'
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Burglary/Theft - Method of Entry <th>
</th> Burglary/Theft - Method of Entry
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.BurglaryTheftMethodOfEntry) <td>
@AjaxHelpers.AjaxSave() @Html.EditorFor(m => m.Job.JobMetaInsurance.BurglaryTheftMethodOfEntry)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
$('#Job_JobMetaInsurance_BurglaryTheftMethodOfEntry'), $('#Job_JobMetaInsurance_BurglaryTheftMethodOfEntry'),
@@ -166,16 +172,17 @@
'BurglaryTheftMethodOfEntry' 'BurglaryTheftMethodOfEntry'
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
<tr> <tr>
<th style="width: 200px;">Property Last Seen <th style="width: 200px;">
</th> Property Last Seen
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.PropertyLastSeenDate) <td>
@AjaxHelpers.AjaxLoader() @Html.EditorFor(m => m.Job.JobMetaInsurance.PropertyLastSeenDate)
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
var dateField = $('#Job_JobMetaInsurance_PropertyLastSeenDate'); var dateField = $('#Job_JobMetaInsurance_PropertyLastSeenDate');
document.DiscoFunctions.DateChangeHelper( document.DiscoFunctions.DateChangeHelper(
@@ -186,36 +193,37 @@
null null
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
<tr> <tr>
<th style="width: 200px;">&nbsp; <th style="width: 200px;">
</th> &nbsp;
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.PoliceNotified)@Html.LabelFor(m => m.Job.JobMetaInsurance.PoliceNotified) <td>
@AjaxHelpers.AjaxSave() @Html.EditorFor(m => m.Job.JobMetaInsurance.PoliceNotified)@Html.LabelFor(m => m.Job.JobMetaInsurance.PoliceNotified)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
<div id="Job_JobMetaInsurance_PoliceNotified_Details" style="padding-left: 25px;"> @AjaxHelpers.AjaxLoader()
<div> <div id="Job_JobMetaInsurance_PoliceNotified_Details" style="padding-left: 25px;">
<h5>Station</h5> <div>
@Html.EditorFor(m => m.Job.JobMetaInsurance.PoliceNotifiedStation) <h5>Station</h5>
@AjaxHelpers.AjaxSave() @Html.EditorFor(m => m.Job.JobMetaInsurance.PoliceNotifiedStation)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
</div>
<div>
<h5>Date</h5>
@Html.EditorFor(m => m.Job.JobMetaInsurance.PoliceNotifiedDate)
@AjaxHelpers.AjaxLoader()
</div>
<div>
<h5>Crime Report #</h5>
@Html.EditorFor(m => m.Job.JobMetaInsurance.PoliceNotifiedCrimeReportNo)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
</div>
</div> </div>
<div> <script type="text/javascript">
<h5>Date</h5>
@Html.EditorFor(m => m.Job.JobMetaInsurance.PoliceNotifiedDate)
@AjaxHelpers.AjaxLoader()
</div>
<div>
<h5>Crime Report #</h5>
@Html.EditorFor(m => m.Job.JobMetaInsurance.PoliceNotifiedCrimeReportNo)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
</div>
</div>
<script type="text/javascript">
$(function () { $(function () {
var policeNotifiedField = $('#Job_JobMetaInsurance_PoliceNotified'); var policeNotifiedField = $('#Job_JobMetaInsurance_PoliceNotified');
var policeNotifiedDetails = $('#Job_JobMetaInsurance_PoliceNotified_Details'); var policeNotifiedDetails = $('#Job_JobMetaInsurance_PoliceNotified_Details');
@@ -265,17 +273,18 @@
'PoliceNotifiedCrimeReportNo' 'PoliceNotifiedCrimeReportNo'
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Action to Recover/Reduce Loss <th>
</th> Action to Recover/Reduce Loss
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.RecoverReduceAction) <td>
@AjaxHelpers.AjaxSave() @Html.EditorFor(m => m.Job.JobMetaInsurance.RecoverReduceAction)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
$('#Job_JobMetaInsurance_RecoverReduceAction'), $('#Job_JobMetaInsurance_RecoverReduceAction'),
@@ -284,17 +293,18 @@
'RecoverReduceAction' 'RecoverReduceAction'
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Other Interested Parties <th>
</th> Other Interested Parties
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.OtherInterestedParties) <td>
@AjaxHelpers.AjaxSave() @Html.EditorFor(m => m.Job.JobMetaInsurance.OtherInterestedParties)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
$('#Job_JobMetaInsurance_OtherInterestedParties'), $('#Job_JobMetaInsurance_OtherInterestedParties'),
@@ -303,16 +313,17 @@
'OtherInterestedParties' 'OtherInterestedParties'
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
<tr> <tr>
<th style="width: 200px;">Date of Purchase <th style="width: 200px;">
</th> Date of Purchase
<td> </th>
@Html.EditorFor(m => m.Job.JobMetaInsurance.DateOfPurchase) <td>
@AjaxHelpers.AjaxLoader() @Html.EditorFor(m => m.Job.JobMetaInsurance.DateOfPurchase)
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
var dateField = $('#Job_JobMetaInsurance_DateOfPurchase'); var dateField = $('#Job_JobMetaInsurance_DateOfPurchase');
document.DiscoFunctions.DateChangeHelper( document.DiscoFunctions.DateChangeHelper(
@@ -324,232 +335,313 @@
true true
); );
}); });
</script> </script>
</td> </td>
</tr> </tr>
} }
else else
{ {
<tr> <tr>
<th style="width: 230px;">Date of Loss or Damage <th style="width: 230px;">
</th> Date of Loss or Damage
<td> </th>
@CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.LossOrDamageDate, "Unknown", null) <td>
</td> @CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.LossOrDamageDate, "Unknown", null)
</tr> </td>
<tr> </tr>
<th>Event Location <tr>
</th> <th>
<td> Event Location
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.EventLocation)) </th>
{ <td>
<span class="smallMessage">&lt;Unknown/None&gt;</span> @if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.EventLocation))
} {
else <span class="smallMessage">&lt;Unknown/None&gt;</span>
{ }
@Model.Job.JobMetaInsurance.EventLocation else
} {
</td> @Model.Job.JobMetaInsurance.EventLocation
</tr> }
<tr> </td>
<th>Description </tr>
</th> <tr>
<td> <th>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.Description)) Description
{ </th>
<span class="smallMessage">&lt;None&gt;</span> <td>
} @if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.Description))
else {
{ <span class="smallMessage">&lt;None&gt;</span>
@Model.Job.JobMetaInsurance.Description }
} else
</td> {
</tr> @Model.Job.JobMetaInsurance.Description
<tr> }
<th style="width: 200px;">Caused by Third Party </td>
</th> </tr>
<td> <tr>
@if (Model.Job.JobMetaInsurance.ThirdPartyCaused) <th style="width: 200px;">
{ Caused by Third Party
<div id="Job_JobMetaInsurance_ThirdPartyCaused_Details" style="padding-left: 25px;"> </th>
<div> <td>
<h5>Third Party Name</h5> @if (Model.Job.JobMetaInsurance.ThirdPartyCaused)
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.ThirdPartyCausedName)) {
{ <div id="Job_JobMetaInsurance_ThirdPartyCaused_Details" style="padding-left: 25px;">
<span class="smallMessage">&lt;Unknown&gt;</span> <div>
} <h5>Third Party Name</h5>
else @if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.ThirdPartyCausedName))
{ {
@Model.Job.JobMetaInsurance.ThirdPartyCausedName <span class="smallMessage">&lt;Unknown&gt;</span>
} }
else
{
@Model.Job.JobMetaInsurance.ThirdPartyCausedName
}
</div>
<div>
<h5>Why Third Parties Fault</h5>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.ThirdPartyCausedWhy))
{
<span class="smallMessage">&lt;Unknown&gt;</span>
}
else
{
@Model.Job.JobMetaInsurance.ThirdPartyCausedWhy
}
</div>
</div> </div>
<div> }
<h5>Why Third Parties Fault</h5> else
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.ThirdPartyCausedWhy)) {
{ <span class="smallMessage">&lt;Not Caused by Third Party&gt;</span>
<span class="smallMessage">&lt;Unknown&gt;</span> }
} </td>
else </tr>
{ <tr>
@Model.Job.JobMetaInsurance.ThirdPartyCausedWhy <th>
} Witnessed by (Name/Address)
</th>
<td>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.WitnessesNamesAddresses))
{
<span class="smallMessage">&lt;Unknown/None&gt;</span>
}
else
{
@Model.Job.JobMetaInsurance.WitnessesNamesAddresses
}
</td>
</tr>
<tr>
<th>
Burglary/Theft - Method of Entry
</th>
<td>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.BurglaryTheftMethodOfEntry))
{
<span class="smallMessage">&lt;Unknown/None&gt;</span>
}
else
{
@Model.Job.JobMetaInsurance.BurglaryTheftMethodOfEntry
}
</td>
</tr>
<tr>
<th style="width: 200px;">
Property Last Seen
</th>
<td>
@CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.PropertyLastSeenDate, "Unknown", null)
</td>
</tr>
<tr>
<th style="width: 200px;">
&nbsp;
Police Notified
</th>
<td>
@if (Model.Job.JobMetaInsurance.PoliceNotified)
{
<div id="Job_JobMetaInsurance_PoliceNotified_Details" style="padding-left: 25px;">
<div>
<h5>Station</h5>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.PoliceNotifiedStation))
{
<span class="smallMessage">&lt;Unknown&gt;</span>
}
else
{
@Model.Job.JobMetaInsurance.PoliceNotifiedStation
}
</div>
<div>
<h5>Date</h5>
@CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.PoliceNotifiedDate, "Unknown", null)
</div>
<div>
<h5>Crime Report #</h5>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.PoliceNotifiedCrimeReportNo))
{
<span class="smallMessage">&lt;Unknown&gt;</span>
}
else
{
@Model.Job.JobMetaInsurance.PoliceNotifiedCrimeReportNo
}
</div>
</div> </div>
</div> }
} else
else {
{ <span class="smallMessage">&lt;Not Notified&gt;</span>
<span class="smallMessage">&lt;Not Caused by Third Party&gt;</span> }
} </td>
</td> </tr>
</tr> <tr>
<tr> <th>
<th>Witnessed by (Name/Address) Action to Recover/Reduce Loss
</th> </th>
<td> <td>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.WitnessesNamesAddresses)) @if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.RecoverReduceAction))
{ {
<span class="smallMessage">&lt;Unknown/None&gt;</span> <span class="smallMessage">&lt;Unknown/None&gt;</span>
} }
else else
{ {
@Model.Job.JobMetaInsurance.WitnessesNamesAddresses @Model.Job.JobMetaInsurance.RecoverReduceAction
} }
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Burglary/Theft - Method of Entry <th>
</th> Other Interested Parties
<td> </th>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.BurglaryTheftMethodOfEntry)) <td>
{ @if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.OtherInterestedParties))
<span class="smallMessage">&lt;Unknown/None&gt;</span> {
} <span class="smallMessage">&lt;Unknown/None&gt;</span>
else }
{ else
@Model.Job.JobMetaInsurance.BurglaryTheftMethodOfEntry {
} @Model.Job.JobMetaInsurance.OtherInterestedParties
</td> }
</tr> </td>
<tr> </tr>
<th style="width: 200px;">Property Last Seen <tr>
</th> <th style="width: 200px;">
<td> Date of Purchase
@CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.PropertyLastSeenDate, "Unknown", null) </th>
</td> <td>
</tr> @CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.DateOfPurchase, "Unknown", null)
<tr> </td>
<th style="width: 200px;">&nbsp; </tr>
Police Notified
</th>
<td>
@if (Model.Job.JobMetaInsurance.PoliceNotified)
{
<div id="Job_JobMetaInsurance_PoliceNotified_Details" style="padding-left: 25px;">
<div>
<h5>Station</h5>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.PoliceNotifiedStation))
{
<span class="smallMessage">&lt;Unknown&gt;</span>
}
else
{
@Model.Job.JobMetaInsurance.PoliceNotifiedStation
}
</div>
<div>
<h5>Date</h5>
@CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.PoliceNotifiedDate, "Unknown", null)
</div>
<div>
<h5>Crime Report #</h5>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.PoliceNotifiedCrimeReportNo))
{
<span class="smallMessage">&lt;Unknown&gt;</span>
}
else
{
@Model.Job.JobMetaInsurance.PoliceNotifiedCrimeReportNo
}
</div>
</div>
}
else
{
<span class="smallMessage">&lt;Not Notified&gt;</span>
}
</td>
</tr>
<tr>
<th>Action to Recover/Reduce Loss
</th>
<td>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.RecoverReduceAction))
{
<span class="smallMessage">&lt;Unknown/None&gt;</span>
}
else
{
@Model.Job.JobMetaInsurance.RecoverReduceAction
}
</td>
</tr>
<tr>
<th>Other Interested Parties
</th>
<td>
@if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.OtherInterestedParties))
{
<span class="smallMessage">&lt;Unknown/None&gt;</span>
}
else
{
@Model.Job.JobMetaInsurance.OtherInterestedParties
}
</td>
</tr>
<tr>
<th style="width: 200px;">Date of Purchase
</th>
<td>
@CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.DateOfPurchase, "Unknown", null)
</td>
</tr>
} }
if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent)) if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent))
{ {
<tr> <tr>
<th>Claim Form Sent Date <th>
</th> Claim Form Sent Date
<td> </th>
@CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.ClaimFormSentDate, "Not Sent", "Job_JobMetaInsurance_ClaimFormSentDate") <td>
<span id="Job_JobMetaInsurance_ClaimFormSentUserId">@(string.IsNullOrEmpty(Model.Job.JobMetaInsurance.ClaimFormSentUserId) ? string.Empty : string.Format("by {0}", Model.Job.JobMetaInsurance.ClaimFormSentUser.ToString()))</span> @CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.ClaimFormSentDate, "Not Sent", "Job_JobMetaInsurance_ClaimFormSentDate")
<script> <span id="Job_JobMetaInsurance_ClaimFormSentUserId">@(string.IsNullOrEmpty(Model.Job.JobMetaInsurance.ClaimFormSentUserId) ? string.Empty : string.Format("by {0}", Model.Job.JobMetaInsurance.ClaimFormSentUser.ToString()))</span>
$(function () { </td>
var updateUrl = '@(Url.Action(MVC.API.Job.Update(Model.Job.Id, null)))'; </tr>
var jobOpenDate = '@(Model.Job.OpenedDate.ToISO8601())'; <tr>
<th>
document.DiscoFunctions.DateDialogCreateUpdater(updateUrl, 'Claim Form Sent Date', 'Job_JobMetaInsurance_ClaimFormSentDate', 'Job_JobMetaInsurance_ClaimFormSentUserId', 'InsuranceClaimFormSentDate', 'Not Sent', jobOpenDate, false); Insurer
}); </th>
</script> <td>
</td> @if (string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.Insurer) && !Model.Job.JobMetaInsurance.ClaimFormSentDate.HasValue)
</tr> {
if (Model.Job.CanLogInsurance())
{
@Html.ActionLinkButton("Lodge Insurance Claim", MVC.Job.LogInsurance(Model.Job.Id, null, null))
}
else
{
<span>Not Logged</span>
}
}
else
{
<span id="Job_JobMetaInsurance_Insurer">@Model.Job.JobMetaInsurance.Insurer</span>
if (!string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.InsurerReference))
{
<span>(reference: <span id="Job_JobMetaInsurance_InsurerReference">@Model.Job.JobMetaInsurance.InsurerReference</span>)</span>
}
}
</td>
</tr>
} }
else else
{ {
<tr> <tr>
<th>Claim Form Sent Date <th>
</th> Claim Form Sent Date
<td> </th>
@CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.ClaimFormSentDate, "Not Sent", "Job_JobMetaInsurance_ClaimFormSentDate") <td>
<span id="Job_JobMetaInsurance_ClaimFormSentUserId">@(string.IsNullOrEmpty(Model.Job.JobMetaInsurance.ClaimFormSentUserId) ? string.Empty : string.Format("by {0}", Model.Job.JobMetaInsurance.ClaimFormSentUser.ToString()))</span> @CommonHelpers.FriendlyDate(Model.Job.JobMetaInsurance.ClaimFormSentDate, "Not Sent", "Job_JobMetaInsurance_ClaimFormSentDate")
</td> <span id="Job_JobMetaInsurance_ClaimFormSentUserId">@(string.IsNullOrEmpty(Model.Job.JobMetaInsurance.ClaimFormSentUserId) ? string.Empty : string.Format("by {0}", Model.Job.JobMetaInsurance.ClaimFormSentUser.ToString()))</span>
</tr> </td>
</tr>
<tr>
<th>
Insurer
</th>
<td>
<span id="Job_JobMetaInsurance_Insurer">@Model.Job.JobMetaInsurance.Insurer</span>
@if (!string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.InsurerReference))
{
<span>(reference: <span id="Job_JobMetaInsurance_InsurerReference">@Model.Job.JobMetaInsurance.InsurerReference</span>)</span>
}
</td>
</tr>
}
if (!string.IsNullOrEmpty(Model.Job.JobMetaInsurance.Insurer))
{
<tr id="jobInsuranceProviderDetailContainer" style="display: none">
<th style="width: 200px;">
Provider Details
</th>
<td>
<div id="jobInsuranceProviderDetailLoading">
<span class="ajaxLoading" title="Loading..."></span>Loading...
</div>
<div id="jobInsuranceProviderDetailHost" class="clearfix" style="display: none">
</div>
</td>
</tr>
<script type="text/javascript">
$(function () {
let providerDetailLoaded = false;
$('#jobDetailTabs').on('tabsactivate', function (e, ui) {
if ($(ui.newPanel).is('#jobDetailTab-NonWarrantyInsurance')) {
if (!providerDetailLoaded) {
$('#jobInsuranceProviderDetailContainer').show();
$('#jobRepairProviderDetailLoading span').show();
$('#jobInsuranceProviderDetailHost').load(
'@(Url.Action(MVC.Job.InsuranceProviderJobDetails(Model.Job.Id)))',
function () {
$('#jobInsuranceProviderDetailLoading').hide();
$(this).slideDown();
}
);
providerDetailLoaded = true;
}
}
});
});
</script>
} }
} }
@if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.IsInsuranceClaim)) @if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.IsInsuranceClaim) && Model.Job.JobMetaInsurance == null || string.IsNullOrWhiteSpace(Model.Job.JobMetaInsurance.Insurer))
{ {
<tr> <tr>
<th>Insurance Claim <th>
Insurance Claim
</th> </th>
<td> <td>
<div style="padding: 8px; text-align: center"> <div style="padding: 8px; text-align: center">
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -128,7 +128,7 @@
<td> <td>
@if (Model.Job.CanLogRepair()) @if (Model.Job.CanLogRepair())
{ {
@Html.ActionLinkSmallButton("Log Repair", MVC.Job.LogRepair(Model.Job.Id, null, null), "Job_Show_Repair_Actions_LogRepair_Button") @Html.ActionLinkSmallButton("Lodge Repair", MVC.Job.LogRepair(Model.Job.Id, null, null), "Job_Show_Repair_Actions_LogRepair_Button")
} }
else else
{ {
@@ -599,14 +599,14 @@ WriteLiteral(">Actions\r\n </th>\r\n <td>\r\n");
#line hidden #line hidden
#line 131 "..\..\Views\Job\JobParts\Repairs.cshtml" #line 131 "..\..\Views\Job\JobParts\Repairs.cshtml"
Write(Html.ActionLinkSmallButton("Log Repair", MVC.Job.LogRepair(Model.Job.Id, null, null), "Job_Show_Repair_Actions_LogRepair_Button")); Write(Html.ActionLinkSmallButton("Lodge Repair", MVC.Job.LogRepair(Model.Job.Id, null, null), "Job_Show_Repair_Actions_LogRepair_Button"));
#line default #line default
#line hidden #line hidden
#line 131 "..\..\Views\Job\JobParts\Repairs.cshtml" #line 131 "..\..\Views\Job\JobParts\Repairs.cshtml"
} }
else else
{ {

Some files were not shown because too many files have changed in this diff Show More