diff --git a/Disco.BI/BI/Extensions/AuthorizationRoleExtensions.cs b/Disco.BI/BI/Extensions/AuthorizationRoleExtensions.cs index 2841ac34..401e36e9 100644 --- a/Disco.BI/BI/Extensions/AuthorizationRoleExtensions.cs +++ b/Disco.BI/BI/Extensions/AuthorizationRoleExtensions.cs @@ -1,5 +1,5 @@ using Disco.Data.Repository; -using Disco.Models.Authorization; +using Disco.Models.Services.Authorization; using Disco.Models.Repository; using Disco.Services.Users; using System; diff --git a/Disco.BI/BI/Extensions/JobActionExtensions.cs b/Disco.BI/BI/Extensions/JobActionExtensions.cs index 84506a98..17311fc2 100644 --- a/Disco.BI/BI/Extensions/JobActionExtensions.cs +++ b/Disco.BI/BI/Extensions/JobActionExtensions.cs @@ -338,20 +338,53 @@ namespace Disco.BI.Extensions #endregion #region Close - public static bool CanClose(this Job j) + public static void OnCloseNormally(this Job j, User Technician) + { + if (!j.CanCloseNormally()) + throw new InvalidOperationException("Close was Denied"); + + j.ClosedDate = DateTime.Now; + j.ClosedTechUserId = Technician.Id; + } + + private static bool CanCloseNever(this Job j, JobQueueJob IgnoreJobQueueJob = null) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Close)) return false; if (j.ClosedDate.HasValue) - return false; // Job already Closed + return true; // Job already Closed if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue) - return false; // Device not returned to User + return true; // Device not returned to User if (j.WaitingForUserAction.HasValue) - return false; // Job waiting on User Action + return true; // Job waiting on User Action + if (IgnoreJobQueueJob == null) + { + if (j.JobQueues.Any(jqj => !jqj.RemovedDate.HasValue)) + return true; // Job associated with a Job Queue + } + else + { + if (j.JobQueues.Any(jqj => jqj.Id != IgnoreJobQueueJob.Id && !jqj.RemovedDate.HasValue)) + return true; // Job associated with a Job Queue + } + + return false; + } + + public static bool CanCloseNormally(this Job j) + { + if (j.CanCloseNever()) + return false; + + return j.CanCloseNormallyInternal(); + } + + private static bool CanCloseNormallyInternal(this Job j) + { switch (j.JobTypeId) { case JobType.JobTypeIds.HWar: @@ -374,36 +407,27 @@ namespace Disco.BI.Extensions return true; } - public static void OnClose(this Job j, User Technician) - { - if (!j.CanClose()) - throw new InvalidOperationException("Close was Denied"); - j.ClosedDate = DateTime.Now; - j.ClosedTechUserId = Technician.Id; + public static bool CanCloseJobNormallyAfterRemoved(this JobQueueJob jqj) + { + if (jqj.Job.CanCloseNever(jqj)) + return false; + + return jqj.Job.CanCloseNormallyInternal(); } #endregion #region Force Close - public static bool CanForceClose(this Job j) + public static bool CanCloseForced(this Job j) { if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ForceClose)) return false; - var canCloseNormally = j.CanClose(); - - if (canCloseNormally) + if (j.CanCloseNever()) return false; - // Check for Override - if (j.ClosedDate.HasValue) - return false; // Job already Closed - - if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue) - return false; // Device not returned to User - - if (j.WaitingForUserAction.HasValue) - return false; // Job waiting on User Action + if (j.CanCloseNormally()) + return false; switch (j.JobTypeId) { @@ -427,9 +451,9 @@ namespace Disco.BI.Extensions return false; } - public static void OnForceClose(this Job j, DiscoDataContext Database, User Technician, string Reason) + public static void OnCloseForced(this Job j, DiscoDataContext Database, User Technician, string Reason) { - if (!j.CanForceClose()) + if (!j.CanCloseForced()) throw new InvalidOperationException("Force Close was Denied"); // Write Log diff --git a/Disco.BI/BI/Extensions/JobExtensions.cs b/Disco.BI/BI/Extensions/JobExtensions.cs index edb4513b..58991895 100644 --- a/Disco.BI/BI/Extensions/JobExtensions.cs +++ b/Disco.BI/BI/Extensions/JobExtensions.cs @@ -44,108 +44,6 @@ namespace Disco.BI.Extensions return ja; } - public static Tuple Status(this Job j) - { - var statusId = j.CalculateStatusId(); - return new Tuple(statusId, JobBI.Utilities.JobStatusDescription(statusId, j)); - } - - public static JobTableModel.JobTableItemModelIncludeStatus ToJobTableItemModelIncludeStatus(this Job j) - { - var i = new JobTableModel.JobTableItemModelIncludeStatus() - { - Id = j.Id, - OpenedDate = j.OpenedDate, - ClosedDate = j.ClosedDate, - TypeId = j.JobTypeId, - TypeDescription = j.JobType.Description, - Location = j.DeviceHeldLocation, - - WaitingForUserAction = j.WaitingForUserAction, - DeviceReadyForReturn = j.DeviceReadyForReturn, - DeviceHeld = j.DeviceHeld, - DeviceReturnedDate = j.DeviceReturnedDate - }; - - if (j.Device != null) - { - i.DeviceSerialNumber = j.DeviceSerialNumber; - i.DeviceModelDescription = j.Device.DeviceModel.Description; - i.DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress; - - if (j.JobMetaWarranty != null) - { - i.JobMetaWarranty_ExternalReference = j.JobMetaWarranty.ExternalReference; - i.JobMetaWarranty_ExternalCompletedDate = j.JobMetaWarranty.ExternalCompletedDate; - i.JobMetaWarranty_ExternalName = j.JobMetaWarranty.ExternalName; - } - if (j.JobMetaNonWarranty != null) - { - i.JobMetaNonWarranty_RepairerLoggedDate = j.JobMetaNonWarranty.RepairerLoggedDate; - i.JobMetaNonWarranty_RepairerCompletedDate = j.JobMetaNonWarranty.RepairerCompletedDate; - i.JobMetaNonWarranty_AccountingChargeAddedDate = j.JobMetaNonWarranty.AccountingChargeAddedDate; - i.JobMetaNonWarranty_AccountingChargePaidDate = j.JobMetaNonWarranty.AccountingChargePaidDate; - i.JobMetaNonWarranty_AccountingChargeRequiredDate = j.JobMetaNonWarranty.AccountingChargeRequiredDate; - i.JobMetaNonWarranty_IsInsuranceClaim = j.JobMetaNonWarranty.IsInsuranceClaim; - i.JobMetaNonWarranty_RepairerName = j.JobMetaNonWarranty.RepairerName; - if (j.JobMetaInsurance != null) - { - i.JobMetaInsurance_ClaimFormSentDate = j.JobMetaInsurance.ClaimFormSentDate; - } - } - - } - if (j.User != null) - { - i.UserId = j.UserId; - i.UserDisplayName = j.User.DisplayName; - } - if (j.OpenedTechUser != null) - { - i.OpenedTechUserId = j.OpenedTechUserId; - i.OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName; - } - - return i; - } - - public static string CalculateStatusId(this Job j) - { - return j.ToJobTableItemModelIncludeStatus().CalculateStatusId(); - } - - public static string CalculateStatusId(this JobTableModel.JobTableItemModelIncludeStatus j) - { - if (j.ClosedDate.HasValue) - return Job.JobStatusIds.Closed; - - if (j.TypeId == JobType.JobTypeIds.HWar) - { - if (!string.IsNullOrEmpty(j.JobMetaWarranty_ExternalReference) && !j.JobMetaWarranty_ExternalCompletedDate.HasValue) - return Job.JobStatusIds.AwaitingWarrantyRepair; // Job Logged - but not marked as completed - } - - if (j.TypeId == JobType.JobTypeIds.HNWar) - { - if (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty_RepairerCompletedDate.HasValue) - return Job.JobStatusIds.AwaitingRepairs; // Repairs logged - but not complete - if (j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue) - return Job.JobStatusIds.AwaitingAccountingPayment; // Accounting Charge Added, but not paid - if (j.JobMetaNonWarranty_AccountingChargeRequiredDate.HasValue && (!j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue || !j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue)) - return Job.JobStatusIds.AwaitingAccountingCharge; // Accounting Charge Required, but not added or paid - if (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && j.JobMetaNonWarranty_IsInsuranceClaim.Value && !j.JobMetaInsurance_ClaimFormSentDate.HasValue) - return Job.JobStatusIds.AwaitingInsuranceProcessing; // Is insurance claim, but no Claim Form Sent - } - - if (j.WaitingForUserAction.HasValue) - return Job.JobStatusIds.AwaitingUserAction; // Awaiting for User - - if (j.DeviceReadyForReturn.HasValue && !j.DeviceReturnedDate.HasValue) - return Job.JobStatusIds.AwaitingDeviceReturn; // Device not returned to User - - return Job.JobStatusIds.Open; - } - public static List AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp) { var dts = Database.DocumentTemplates.Include("JobSubTypes") diff --git a/Disco.BI/BI/Extensions/JobQueueActionExtensions.cs b/Disco.BI/BI/Extensions/JobQueueActionExtensions.cs new file mode 100644 index 00000000..e809fbc4 --- /dev/null +++ b/Disco.BI/BI/Extensions/JobQueueActionExtensions.cs @@ -0,0 +1,216 @@ +using Disco.Data.Repository; +using Disco.Models.Repository; +using Disco.Services.Authorization; +using Disco.Services.Jobs.JobQueues; +using Disco.Services.Users; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.BI.Extensions +{ + public static class JobQueueActionExtensions + { + + #region Edit Sla + public static bool CanEditSla(this JobQueueJob jqj) + { + if (jqj.RemovedDate.HasValue) + return false; + + if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnySLA)) + { + // Can edit ANY queue + return true; + } + else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnSLA)) + { + // Can edit from OWN queue + return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId); + } + else + { + return false; + } + } + public static void OnEditSla(this JobQueueJob jqj, DateTime? SlaExpiresDate) + { + if (!jqj.CanEditSla()) + throw new InvalidOperationException("Editing job SLA for this queue is denied"); + + if (SlaExpiresDate.HasValue && jqj.AddedDate > SlaExpiresDate.Value) + throw new ArgumentException("The SLA Expires Date must be greater than the Added Date", "SLAExpiresDate"); + + jqj.SLAExpiresDate = SlaExpiresDate; + } + #endregion + + #region Edit Priority + public static bool CanEditPriority(this JobQueueJob jqj) + { + if (jqj.RemovedDate.HasValue) + return false; + + if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnyPriority)) + { + // Can edit ANY queue + return true; + } + else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnPriority)) + { + // Can edit from OWN queue + return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId); + } + else + { + return false; + } + } + public static void OnEditPriority(this JobQueueJob jqj, JobQueuePriority Priority) + { + if (!jqj.CanEditPriority()) + throw new InvalidOperationException("Editing job priority for this queue is denied"); + + jqj.Priority = Priority; + } + #endregion + + #region Edit Comments + private static bool CanEditComments(this JobQueueJob jqj) + { + if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnyComments)) + { + // Can edit ANY queue + return true; + } + else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnComments)) + { + // Can edit from OWN queue + return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId); + } + else + { + return false; + } + } + public static bool CanEditAddedComment(this JobQueueJob jqj) + { + return jqj.CanEditComments(); + } + public static bool CanEditRemovedComment(this JobQueueJob jqj) + { + if (!jqj.RemovedDate.HasValue) + return false; + + return jqj.CanEditComments(); + } + public static void OnEditAddedComment(this JobQueueJob jqj, string AddedComment) + { + if (!jqj.CanEditAddedComment()) + throw new InvalidOperationException("Editing job added comments for this queue is denied"); + + jqj.AddedComment = string.IsNullOrWhiteSpace(AddedComment) ? null : AddedComment.Trim(); + } + public static void OnEditRemovedComment(this JobQueueJob jqj, string RemovedComment) + { + if (!jqj.CanEditRemovedComment()) + throw new InvalidOperationException("Editing job removed comments for this queue is denied"); + + jqj.RemovedComment = string.IsNullOrWhiteSpace(RemovedComment) ? null : RemovedComment.Trim(); + } + #endregion + + #region Remove + public static bool CanRemove(this JobQueueJob jqj) + { + if (jqj.RemovedDate.HasValue) + return false; + + if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveAnyQueues)) + { + // Can remove from ANY queue + return true; + } + else if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveOwnQueues)) + { + // Can remove from OWN queue + return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId); + } + else + { + return false; + } + } + public static void OnRemove(this JobQueueJob jqj, User Technician, string Comment) + { + if (!jqj.CanRemove()) + throw new InvalidOperationException("Removing job from queue is Denied"); + + jqj.RemovedDate = DateTime.Now; + jqj.RemovedUserId = Technician.Id; + jqj.RemovedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim(); + } + #endregion + + #region Add + public static bool CanAddQueues(this Job j) + { + // Job Closed? + if (j.ClosedDate.HasValue) + return false; + + if (UserService.CurrentAuthorization.HasAny(Claims.Job.Actions.AddAnyQueues, Claims.Job.Actions.AddOwnQueues)) + return true; + + return false; + } + public static bool CanAddQueue(this Job j, JobQueue jq) + { + // Shortcut + if (!j.CanAddQueues()) + return false; + + // Already in Queue? + if (j.JobQueues.Count(jjq => !jjq.RemovedDate.HasValue && jjq.JobQueueId == jq.Id) > 0) + return false; + + // Can add ANY queue + if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.AddAnyQueues)) + return true; + + // Can add OWN queue + if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.AddOwnQueues)) + { + return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jq.Id); + } + + return false; + } + public static JobQueueJob OnAddQueue(this Job j, DiscoDataContext Database, JobQueue jq, User Technician, string Comment, DateTime? SLAExpires, JobQueuePriority Priority) + { + if (!j.CanAddQueue(jq)) + throw new InvalidOperationException("Adding job to queue is Denied"); + + if (SLAExpires.HasValue && SLAExpires.Value < DateTime.Now) + throw new ArgumentException("The SLA Date must be greater than the current time", "SLAExpires"); + + var jqj = new JobQueueJob() + { + JobQueueId = jq.Id, + JobId = j.Id, + AddedDate = DateTime.Now, + AddedUserId = Technician.Id, + AddedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim(), + SLAExpiresDate = SLAExpires, + Priority = Priority + }; + + Database.JobQueueJobs.Add(jqj); + return jqj; + } + #endregion + + } +} diff --git a/Disco.BI/BI/JobBI/ManagedJobList.cs b/Disco.BI/BI/JobBI/ManagedJobList.cs deleted file mode 100644 index 9ae38697..00000000 --- a/Disco.BI/BI/JobBI/ManagedJobList.cs +++ /dev/null @@ -1,188 +0,0 @@ -using Disco.Data.Repository; -using Disco.Data.Repository.Monitor; -using Disco.Models.BI.Job; -using Disco.Models.Repository; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Disco.BI.Extensions; -using System.Reactive.Linq; -using Disco.Services.Users; - -namespace Disco.BI.JobBI -{ - using FilterFunc = Func, IQueryable>; - using SortFunc = Func, IEnumerable>; - using Disco.Services.Logging; - - public class ManagedJobList : JobTableModel, IDisposable - { - public string Name { get; set; } - public FilterFunc FilterFunction { get; set; } - public SortFunc SortFunction { get; set; } - private IDisposable unsubscribeToken; - private object updateLock = new object(); - - public override List Items - { - get - { - return base.Items.PermissionsFiltered(UserService.CurrentAuthorization); - } - set - { - throw new InvalidOperationException("Items cannot be manually set in a Managed Job List"); - } - } - - public ManagedJobList Initialize(DiscoDataContext Database) - { - // Can only Initialize once - if (base.Items != null) - return ReInitialize(Database); - - lock (updateLock) - { - // Subscribe for Changes - // - Job (or Job Meta) Changes - // - Device Profile Address Changes (for multi-campus Schools) - // - Device Model Description Changes - // - Device's Profile or Model Changes - unsubscribeToken = RepositoryMonitor.StreamAfterCommit - .Where(n => n.EntityType == typeof(Job) || - n.EntityType == typeof(JobMetaWarranty) || - n.EntityType == typeof(JobMetaNonWarranty) || - n.EntityType == typeof(JobMetaInsurance) || - (n.EventType == RepositoryMonitorEventType.Modified && ( - (n.EntityType == typeof(DeviceProfile) && n.ModifiedProperties.Contains("DefaultOrganisationAddress")) || - (n.EntityType == typeof(DeviceModel) && n.ModifiedProperties.Contains("Description")) || - (n.EntityType == typeof(Device) && n.ModifiedProperties.Contains("DeviceProfileId") || n.ModifiedProperties.Contains("DeviceModelId")) - ))) - .Subscribe(JobNotification, NotificationError); - - // Initially fill table - base.Items = this.SortFunction(this.DetermineItems(Database, this.FilterFunction(Database.Jobs))).ToList(); - } - return this; - } - - public ManagedJobList ReInitialize(DiscoDataContext Database) - { - return ReInitialize(Database, null, null); - } - public ManagedJobList ReInitialize(DiscoDataContext Database, FilterFunc FilterFunction) - { - return ReInitialize(Database, FilterFunction, null); - } - public ManagedJobList ReInitialize(DiscoDataContext Database, FilterFunc FilterFunction, SortFunc SortFunction) - { - if (Database == null) - throw new ArgumentNullException("Database"); - - lock (updateLock) - { - if (FilterFunction != null) - this.FilterFunction = FilterFunction; - if (SortFunction != null) - this.SortFunction = SortFunction; - - base.Items = this.SortFunction(this.DetermineItems(Database, this.FilterFunction(Database.Jobs))).ToList(); - } - return this; - } - - private void NotificationError(Exception ex) - { - SystemLog.LogException(string.Format("Disco.BI.JobBI.ManagedJobList: [{0}]", this.Name), ex); - } - - private void JobNotification(RepositoryMonitorEvent e) - { - List jobIds = null; - JobTableItemModel[] existingItems = null; - - if (e.EntityType == typeof(Job)) - jobIds = new List() { ((Job)e.Entity).Id }; - else - if (e.EntityType == typeof(JobMetaWarranty)) - jobIds = new List() { ((JobMetaWarranty)e.Entity).JobId }; - else - if (e.EntityType == typeof(JobMetaNonWarranty)) - jobIds = new List() { ((JobMetaNonWarranty)e.Entity).JobId }; - else - if (e.EntityType == typeof(JobMetaInsurance)) - jobIds = new List() { ((JobMetaInsurance)e.Entity).JobId }; - else - if (e.EntityType == typeof(DeviceProfile)) - { - int deviceProfileId = ((DeviceProfile)e.Entity).Id; - existingItems = base.Items.Where(i => i.DeviceProfileId == deviceProfileId).ToArray(); - } - else - if (e.EntityType == typeof(DeviceModel)) - { - int deviceModelId = ((DeviceModel)e.Entity).Id; - existingItems = base.Items.Where(i => i.DeviceModelId == deviceModelId).ToArray(); - } - else - if (e.EntityType == typeof(Device)) - { - string deviceSerialNumber = ((Device)e.Entity).SerialNumber; - existingItems = base.Items.Where(i => i.DeviceSerialNumber == deviceSerialNumber).ToArray(); - } - else - return; // Subscription should never reach - - if (jobIds == null) - { - if (existingItems == null) - throw new InvalidOperationException("Notification algorithm didn't indicate any Jobs for update"); - else - jobIds = existingItems.Select(i => i.Id).ToList(); - } - - if (jobIds.Count == 0) - return; - else - UpdateJobs(e.Database, jobIds, existingItems); - } - - private void UpdateJobs(DiscoDataContext Database, List jobIds, JobTableItemModel[] existingItems = null) - { - lock (updateLock) - { - // Check for existing items, if not handed them - if (existingItems == null) - existingItems = base.Items.Where(i => jobIds.Contains(i.Id)).ToArray(); - - var updatedItems = this.DetermineItems(Database, this.FilterFunction(Database.Jobs.Where(j => jobIds.Contains(j.Id)))); - - var refreshedList = base.Items.ToList(); - - // Remove Existing - if (existingItems.Length > 0) - foreach (var existingItem in existingItems) - refreshedList.Remove(existingItem); - - // Add Updated Items - if (updatedItems.Count > 0) - foreach (var updatedItem in updatedItems) - refreshedList.Add(updatedItem); - - // Reorder - base.Items = this.SortFunction(refreshedList).ToList(); - } - } - - public void Dispose() - { - if (unsubscribeToken != null) - { - unsubscribeToken.Dispose(); - unsubscribeToken = null; - } - } - } -} diff --git a/Disco.BI/BI/JobBI/Searching.cs b/Disco.BI/BI/JobBI/Searching.cs index 6b6ecf9c..88a3477f 100644 --- a/Disco.BI/BI/JobBI/Searching.cs +++ b/Disco.BI/BI/JobBI/Searching.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Disco.Models.BI.Job; -using Disco.Data.Repository; +using Disco.Data.Repository; using Disco.Models.Repository; -using Disco.BI.Extensions; +using Disco.Models.Services.Jobs.JobLists; +using Disco.Services; +using System.Linq; namespace Disco.BI.JobBI { diff --git a/Disco.BI/BI/JobBI/Utilities.cs b/Disco.BI/BI/JobBI/Utilities.cs index f043e825..2a4a21e5 100644 --- a/Disco.BI/BI/JobBI/Utilities.cs +++ b/Disco.BI/BI/JobBI/Utilities.cs @@ -40,6 +40,34 @@ namespace Disco.BI.JobBI Database.Jobs.Add(j); + // Job Queues + var queues = from st in subTypes + from jq in st.JobQueues + group st by jq into g + select new { queue = g.Key, subTypes = g }; + foreach (var queue in queues) + { + var commentBuilder = new StringBuilder("Automatically added by:"); + foreach (var subType in queue.subTypes) + { + commentBuilder.AppendLine(); + commentBuilder.Append(subType.Description); + } + + var jqj = new JobQueueJob() + { + JobQueueId = queue.queue.Id, + Job = j, + AddedDate = DateTime.Now, + AddedUserId = initialTech.Id, + AddedComment = commentBuilder.ToString(), + SLAExpiresDate = queue.queue.DefaultSLAExpiry.HasValue ? (DateTime?)DateTime.Now.AddMinutes(queue.queue.DefaultSLAExpiry.Value) : null, + Priority = JobQueuePriority.Normal + }; + + Database.JobQueueJobs.Add(jqj); + } + switch (type.Id) { case JobType.JobTypeIds.HWar: @@ -89,83 +117,5 @@ namespace Disco.BI.JobBI return j; } - - public static string JobStatusDescription(string StatusId, Job j = null) - { - switch (StatusId) - { - case Job.JobStatusIds.Open: - return "Open"; - case Job.JobStatusIds.Closed: - return "Closed"; - case Job.JobStatusIds.AwaitingWarrantyRepair: - if (j == null) - return "Awaiting Warranty Repair"; - else - if (j.DeviceHeld.HasValue) - return string.Format("Awaiting Warranty Repair ({0})", j.JobMetaWarranty.ExternalName); - else - return string.Format("Awaiting Warranty Repair - Not Held ({0})", j.JobMetaWarranty.ExternalName); - case Job.JobStatusIds.AwaitingRepairs: - if (j == null) - return "Awaiting Repairs"; - else - if (j.DeviceHeld.HasValue) - return string.Format("Awaiting Repairs ({0})", j.JobMetaNonWarranty.RepairerName); - else - return string.Format("Awaiting Repairs - Not Held ({0})", j.JobMetaNonWarranty.RepairerName); - case Job.JobStatusIds.AwaitingDeviceReturn: - return "Awaiting Device Return"; - case Job.JobStatusIds.AwaitingUserAction: - return "Awaiting User Action"; - case Job.JobStatusIds.AwaitingAccountingPayment: - return "Awaiting Accounting Payment"; - case Job.JobStatusIds.AwaitingAccountingCharge: - return "Awaiting Accounting Charge"; - case Job.JobStatusIds.AwaitingInsuranceProcessing: - return "Awaiting Insurance Processing"; - default: - return "Unknown"; - } - } - public static string JobStatusDescription(string StatusId, JobTableModel.JobTableItemModelIncludeStatus j = null) - { - switch (StatusId) - { - case Job.JobStatusIds.Open: - return "Open"; - case Job.JobStatusIds.Closed: - return "Closed"; - case Job.JobStatusIds.AwaitingWarrantyRepair: - if (j == null) - return "Awaiting Warranty Repair"; - else - if (j.DeviceHeld.HasValue) - return string.Format("Awaiting Warranty Repair ({0})", j.JobMetaWarranty_ExternalName); - else - return string.Format("Awaiting Warranty Repair - Not Held ({0})", j.JobMetaWarranty_ExternalName); - case Job.JobStatusIds.AwaitingRepairs: - if (j == null) - return "Awaiting Repairs"; - else - if (j.DeviceHeld.HasValue) - return string.Format("Awaiting Repairs ({0})", j.JobMetaNonWarranty_RepairerName); - else - return string.Format("Awaiting Repairs - Not Held ({0})", j.JobMetaNonWarranty_RepairerName); - case Job.JobStatusIds.AwaitingDeviceReturn: - return "Awaiting Device Return"; - case Job.JobStatusIds.AwaitingUserAction: - return "Awaiting User Action"; - case Job.JobStatusIds.AwaitingAccountingPayment: - return "Awaiting Accounting Payment"; - case Job.JobStatusIds.AwaitingAccountingCharge: - return "Awaiting Accounting Charge"; - case Job.JobStatusIds.AwaitingInsuranceProcessing: - return "Awaiting Insurance Processing"; - default: - return "Unknown"; - } - } - } } diff --git a/Disco.BI/Disco.BI.csproj b/Disco.BI/Disco.BI.csproj index 937ee5f6..d7b87a9b 100644 --- a/Disco.BI/Disco.BI.csproj +++ b/Disco.BI/Disco.BI.csproj @@ -155,7 +155,7 @@ - + @@ -196,7 +196,6 @@ - diff --git a/Disco.BI/Properties/AssemblyInfo.cs b/Disco.BI/Properties/AssemblyInfo.cs index 426e0c0d..94ff9f23 100644 --- a/Disco.BI/Properties/AssemblyInfo.cs +++ b/Disco.BI/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.1128.1503")] -[assembly: AssemblyFileVersion("1.2.1128.1503")] \ No newline at end of file +[assembly: AssemblyVersion("1.2.1229.1537")] +[assembly: AssemblyFileVersion("1.2.1229.1537")] \ No newline at end of file diff --git a/Disco.Data/Disco.Data.csproj b/Disco.Data/Disco.Data.csproj index df37978f..b920b1d0 100644 --- a/Disco.Data/Disco.Data.csproj +++ b/Disco.Data/Disco.Data.csproj @@ -126,6 +126,10 @@ 201310282325491_DBv11.cs + + + 201401270857381_DBv12.cs + @@ -174,6 +178,9 @@ 201310282325491_DBv11.cs + + 201401270857381_DBv12.cs + ResXFileCodeGenerator Resources.Designer.cs diff --git a/Disco.Data/Migrations/201401270857381_DBv12.Designer.cs b/Disco.Data/Migrations/201401270857381_DBv12.Designer.cs new file mode 100644 index 00000000..c7c22d7f --- /dev/null +++ b/Disco.Data/Migrations/201401270857381_DBv12.Designer.cs @@ -0,0 +1,27 @@ +// +namespace Disco.Data.Migrations +{ + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + public sealed partial class DBv12 : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(DBv12)); + + string IMigrationMetadata.Id + { + get { return "201401270857381_DBv12"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/Disco.Data/Migrations/201401270857381_DBv12.cs b/Disco.Data/Migrations/201401270857381_DBv12.cs new file mode 100644 index 00000000..f632781d --- /dev/null +++ b/Disco.Data/Migrations/201401270857381_DBv12.cs @@ -0,0 +1,86 @@ +namespace Disco.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class DBv12 : DbMigration + { + public override void Up() + { + CreateTable( + "dbo.JobQueueJobs", + c => new + { + Id = c.Int(nullable: false, identity: true), + JobQueueId = c.Int(nullable: false), + JobId = c.Int(nullable: false), + AddedDate = c.DateTime(nullable: false), + AddedUserId = c.String(nullable: false, maxLength: 50), + AddedComment = c.String(), + RemovedDate = c.DateTime(), + RemovedUserId = c.String(maxLength: 50), + RemovedComment = c.String(), + SLAExpiresDate = c.DateTime(), + Priority = c.Byte(nullable: false), + }) + .PrimaryKey(t => t.Id) + .ForeignKey("dbo.JobQueues", t => t.JobQueueId) + .ForeignKey("dbo.Jobs", t => t.JobId) + .ForeignKey("dbo.Users", t => t.AddedUserId) + .ForeignKey("dbo.Users", t => t.RemovedUserId) + .Index(t => t.JobQueueId) + .Index(t => t.JobId) + .Index(t => t.AddedUserId) + .Index(t => t.RemovedUserId); + + CreateTable( + "dbo.JobQueues", + c => new + { + Id = c.Int(nullable: false, identity: true), + Name = c.String(nullable: false, maxLength: 100), + Description = c.String(nullable: false, maxLength: 500), + Icon = c.String(nullable: false, maxLength: 25), + IconColour = c.String(nullable: false, maxLength: 10), + DefaultSLAExpiry = c.Int(), + Priority = c.Byte(nullable: false), + SubjectIds = c.String(), + }) + .PrimaryKey(t => t.Id); + + CreateTable( + "dbo.JobQueues_JobSubTypes", + c => new + { + JobQueue_Id = c.Int(nullable: false), + JobSubType_Id = c.String(nullable: false, maxLength: 20), + JobSubType_JobTypeId = c.String(nullable: false, maxLength: 5), + }) + .PrimaryKey(t => new { t.JobQueue_Id, t.JobSubType_Id, t.JobSubType_JobTypeId }) + .ForeignKey("dbo.JobQueues", t => t.JobQueue_Id, cascadeDelete: true) + .ForeignKey("dbo.JobSubTypes", t => new { t.JobSubType_Id, t.JobSubType_JobTypeId }, cascadeDelete: true) + .Index(t => t.JobQueue_Id) + .Index(t => new { t.JobSubType_Id, t.JobSubType_JobTypeId }); + + } + + public override void Down() + { + DropIndex("dbo.JobQueues_JobSubTypes", new[] { "JobSubType_Id", "JobSubType_JobTypeId" }); + DropIndex("dbo.JobQueues_JobSubTypes", new[] { "JobQueue_Id" }); + DropIndex("dbo.JobQueueJobs", new[] { "RemovedUserId" }); + DropIndex("dbo.JobQueueJobs", new[] { "AddedUserId" }); + DropIndex("dbo.JobQueueJobs", new[] { "JobId" }); + DropIndex("dbo.JobQueueJobs", new[] { "JobQueueId" }); + DropForeignKey("dbo.JobQueues_JobSubTypes", new[] { "JobSubType_Id", "JobSubType_JobTypeId" }, "dbo.JobSubTypes"); + DropForeignKey("dbo.JobQueues_JobSubTypes", "JobQueue_Id", "dbo.JobQueues"); + DropForeignKey("dbo.JobQueueJobs", "RemovedUserId", "dbo.Users"); + DropForeignKey("dbo.JobQueueJobs", "AddedUserId", "dbo.Users"); + DropForeignKey("dbo.JobQueueJobs", "JobId", "dbo.Jobs"); + DropForeignKey("dbo.JobQueueJobs", "JobQueueId", "dbo.JobQueues"); + DropTable("dbo.JobQueues_JobSubTypes"); + DropTable("dbo.JobQueues"); + DropTable("dbo.JobQueueJobs"); + } + } +} diff --git a/Disco.Data/Migrations/201401270857381_DBv12.resx b/Disco.Data/Migrations/201401270857381_DBv12.resx new file mode 100644 index 00000000..9286e187 --- /dev/null +++ b/Disco.Data/Migrations/201401270857381_DBv12.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + \ No newline at end of file diff --git a/Disco.Data/Properties/AssemblyInfo.cs b/Disco.Data/Properties/AssemblyInfo.cs index be63b3a7..a1e488ff 100644 --- a/Disco.Data/Properties/AssemblyInfo.cs +++ b/Disco.Data/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.1128.1503")] -[assembly: AssemblyFileVersion("1.2.1128.1503")] \ No newline at end of file +[assembly: AssemblyVersion("1.2.1229.1537")] +[assembly: AssemblyFileVersion("1.2.1229.1537")] \ No newline at end of file diff --git a/Disco.Data/Repository/DiscoDataContext.cs b/Disco.Data/Repository/DiscoDataContext.cs index 73d84d7a..aa3f09b9 100644 --- a/Disco.Data/Repository/DiscoDataContext.cs +++ b/Disco.Data/Repository/DiscoDataContext.cs @@ -48,6 +48,9 @@ namespace Disco.Data.Repository public virtual DbSet JobMetaNonWarranties { get; set; } public virtual DbSet JobMetaInsurances { get; set; } + public virtual DbSet JobQueues { get; set; } + public virtual DbSet JobQueueJobs { get; set; } + public Configuration.SystemConfiguration DiscoConfiguration { get @@ -62,6 +65,7 @@ namespace Disco.Data.Repository modelBuilder.Entity().HasMany(m => m.JobSubTypes).WithMany(m => m.DeviceComponents).Map(m => m.ToTable("DeviceComponents_JobSubTypes")); modelBuilder.Entity().HasMany(m => m.JobSubTypes).WithMany(m => m.AttachmentTypes).Map(m => m.ToTable("DocumentTemplates_JobSubTypes")); + modelBuilder.Entity().HasMany(m => m.JobSubTypes).WithMany(m => m.JobQueues).Map(m => m.ToTable("JobQueues_JobSubTypes")); modelBuilder.Entity().HasMany(m => m.JobSubTypes).WithMany(m => m.Jobs).Map(m => m.ToTable("Jobs_JobSubTypes")); modelBuilder.Entity().HasMany(m => m.Jobs).WithOptional(m => m.User); diff --git a/Disco.Models/BI/Config/OrganisationAddress.cs b/Disco.Models/BI/Config/OrganisationAddress.cs index 7b4dc69b..74871cf8 100644 --- a/Disco.Models/BI/Config/OrganisationAddress.cs +++ b/Disco.Models/BI/Config/OrganisationAddress.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.ComponentModel.DataAnnotations; +using System.Text; namespace Disco.Models.BI.Config { diff --git a/Disco.Models/BI/Device/ImportDevice.cs b/Disco.Models/BI/Device/ImportDevice.cs index bdc5dd09..bfb9f1de 100644 --- a/Disco.Models/BI/Device/ImportDevice.cs +++ b/Disco.Models/BI/Device/ImportDevice.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Disco.Models.BI.Device { diff --git a/Disco.Models/BI/Device/ImportDeviceSession.cs b/Disco.Models/BI/Device/ImportDeviceSession.cs index da3f3893..297716d7 100644 --- a/Disco.Models/BI/Device/ImportDeviceSession.cs +++ b/Disco.Models/BI/Device/ImportDeviceSession.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; namespace Disco.Models.BI.Device { diff --git a/Disco.Models/BI/DocumentTemplate/DocumentState.cs b/Disco.Models/BI/DocumentTemplate/DocumentState.cs index 6ba1f3b5..6968cad6 100644 --- a/Disco.Models/BI/DocumentTemplate/DocumentState.cs +++ b/Disco.Models/BI/DocumentTemplate/DocumentState.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Collections; namespace Disco.Models.BI.DocumentTemplates diff --git a/Disco.Models/BI/Expressions/IImageExpressionResult.cs b/Disco.Models/BI/Expressions/IImageExpressionResult.cs index ac2f94d8..f36857c9 100644 --- a/Disco.Models/BI/Expressions/IImageExpressionResult.cs +++ b/Disco.Models/BI/Expressions/IImageExpressionResult.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; +using System.IO; namespace Disco.Models.BI.Expressions { diff --git a/Disco.Models/BI/Job/JobTableModel.cs b/Disco.Models/BI/Job/JobTableModel.cs deleted file mode 100644 index e5368318..00000000 --- a/Disco.Models/BI/Job/JobTableModel.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Disco.Models.BI.Job -{ - public class JobTableModel - { - public bool ShowId { get; set; } - public bool? ShowDeviceAddress { get; set; } - public bool ShowDates { get; set; } - public bool ShowType { get; set; } - public bool ShowDevice { get; set; } - public bool ShowUser { get; set; } - public bool ShowTechnician { get; set; } - public bool ShowLocation { get; set; } - public bool ShowStatus { get; set; } - public bool IsSmallTable { get; set; } - public bool HideClosedJobs { get; set; } - public bool EnablePaging { get; set; } - public bool EnableFilter { get; set; } - public virtual List Items { get; set; } - - public JobTableModel() - { - ShowId = true; - ShowDates = true; - ShowType = true; - ShowDevice = true; - ShowUser = true; - ShowTechnician = true; - EnablePaging = true; - EnableFilter = true; - } - - private JobTableModel CloneEmptyModel() - { - return new JobTableModel() - { - ShowId = this.ShowId, - ShowDeviceAddress = this.ShowDeviceAddress, - ShowDates = this.ShowDates, - ShowType = this.ShowType, - ShowDevice = this.ShowDevice, - ShowUser = this.ShowUser, - ShowTechnician = this.ShowTechnician, - ShowLocation = this.ShowLocation, - ShowStatus = this.ShowStatus, - IsSmallTable = this.IsSmallTable, - HideClosedJobs = this.HideClosedJobs, - EnablePaging = this.EnablePaging, - EnableFilter = this.EnableFilter - }; - } - - public IDictionary MultiCampusModels - { - get - { - var items = this.Items; - if (items == null || items.Count > 0) - { - return items.OrderBy(i => i.DeviceAddress).GroupBy(i => i.DeviceAddress).ToDictionary( - ig => ig.Key ?? string.Empty, - ig => - { - var jtm = this.CloneEmptyModel(); - jtm.Items = ig.ToList(); - return jtm; - } - ); - } - else - { - return null; - } - } - } - - public class JobTableItemModel - { - public int Id { get; set; } - public DateTime OpenedDate { get; set; } - public DateTime? ClosedDate { get; set; } - public string TypeId { get; set; } - public string TypeDescription { get; set; } - public string DeviceSerialNumber { get; set; } - public int? DeviceModelId { get; set; } - public string DeviceModelDescription { get; set; } - public int? DeviceProfileId { get; set; } - public int? DeviceAddressId { get; set; } - public string DeviceAddress { get; set; } - public string UserId { get; set; } - public string UserDisplayName { get; set; } - public string OpenedTechUserId { get; set; } - public string OpenedTechUserDisplayName { get; set; } - public string StatusDescription { get; set; } - public string StatusId { get; set; } - public string Location { get; set; } - } - - public class JobTableItemModelIncludeStatus : JobTableItemModel - { - public string JobMetaWarranty_ExternalReference { get; set; } - public DateTime? JobMetaWarranty_ExternalCompletedDate { get; set; } - - public DateTime? JobMetaNonWarranty_RepairerLoggedDate { get; set; } - public DateTime? JobMetaNonWarranty_RepairerCompletedDate { get; set; } - public DateTime? JobMetaNonWarranty_AccountingChargeAddedDate { get; set; } - public DateTime? JobMetaNonWarranty_AccountingChargePaidDate { get; set; } - public DateTime? JobMetaNonWarranty_AccountingChargeRequiredDate { get; set; } - public bool? JobMetaNonWarranty_IsInsuranceClaim { get; set; } - public DateTime? JobMetaInsurance_ClaimFormSentDate { get; set; } - - public DateTime? WaitingForUserAction { get; set; } - public DateTime? DeviceReadyForReturn { get; set; } - public DateTime? DeviceHeld { get; set; } - public DateTime? DeviceReturnedDate { get; set; } - public string JobMetaWarranty_ExternalName { get; set; } - public string JobMetaNonWarranty_RepairerName { get; set; } - } - } -} diff --git a/Disco.Models/BI/Job/Statistics/DailyOpenedClosedItem.cs b/Disco.Models/BI/Job/Statistics/DailyOpenedClosedItem.cs index 38769700..df79a7b9 100644 --- a/Disco.Models/BI/Job/Statistics/DailyOpenedClosedItem.cs +++ b/Disco.Models/BI/Job/Statistics/DailyOpenedClosedItem.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Disco.Models.BI.Job.Statistics { diff --git a/Disco.Models/BI/Search/DeviceSearchResultItem.cs b/Disco.Models/BI/Search/DeviceSearchResultItem.cs index 7149ca92..f176fd33 100644 --- a/Disco.Models/BI/Search/DeviceSearchResultItem.cs +++ b/Disco.Models/BI/Search/DeviceSearchResultItem.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Disco.Models.BI.Search { diff --git a/Disco.Models/BI/Search/UserSearchResultItem.cs b/Disco.Models/BI/Search/UserSearchResultItem.cs index c829330b..f686c187 100644 --- a/Disco.Models/BI/Search/UserSearchResultItem.cs +++ b/Disco.Models/BI/Search/UserSearchResultItem.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - + namespace Disco.Models.BI.Search { public class UserSearchResultItem diff --git a/Disco.Models/Disco.Models.csproj b/Disco.Models/Disco.Models.csproj index 96286b1c..81ac4cbf 100644 --- a/Disco.Models/Disco.Models.csproj +++ b/Disco.Models/Disco.Models.csproj @@ -45,9 +45,9 @@ - - - + + + @@ -62,7 +62,6 @@ - @@ -100,10 +99,18 @@ + + + + + + + + @@ -132,6 +139,9 @@ + + + diff --git a/Disco.Models/Properties/AssemblyInfo.cs b/Disco.Models/Properties/AssemblyInfo.cs index 78b22e63..35c7a5c3 100644 --- a/Disco.Models/Properties/AssemblyInfo.cs +++ b/Disco.Models/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.1128.1503")] -[assembly: AssemblyFileVersion("1.2.1128.1503")] \ No newline at end of file +[assembly: AssemblyVersion("1.2.1229.1537")] +[assembly: AssemblyFileVersion("1.2.1229.1537")] \ No newline at end of file diff --git a/Disco.Models/Repository/Job/Job.cs b/Disco.Models/Repository/Job/Job.cs index 9f645050..5fcd67ed 100644 --- a/Disco.Models/Repository/Job/Job.cs +++ b/Disco.Models/Repository/Job/Job.cs @@ -70,6 +70,8 @@ namespace Disco.Models.Repository public virtual IList JobComponents { get; set; } public virtual IList JobLogs { get; set; } + public virtual IList JobQueues { get; set; } + public virtual JobMetaInsurance JobMetaInsurance { get; set; } public virtual JobMetaWarranty JobMetaWarranty { get; set; } public virtual JobMetaNonWarranty JobMetaNonWarranty { get; set; } diff --git a/Disco.Models/Repository/Job/JobSubType.cs b/Disco.Models/Repository/Job/JobSubType.cs index 1027693d..8fd0aad4 100644 --- a/Disco.Models/Repository/Job/JobSubType.cs +++ b/Disco.Models/Repository/Job/JobSubType.cs @@ -18,6 +18,7 @@ namespace Disco.Models.Repository public virtual IList AttachmentTypes { get; set; } public virtual IList DeviceComponents { get; set; } + public virtual IList JobQueues { get; set; } [ForeignKey("JobTypeId")] public virtual JobType JobType { get; set; } diff --git a/Disco.Models/Repository/Job/Queue/JobQueue.cs b/Disco.Models/Repository/Job/Queue/JobQueue.cs new file mode 100644 index 00000000..30cb20af --- /dev/null +++ b/Disco.Models/Repository/Job/Queue/JobQueue.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Models.Repository +{ + public class JobQueue + { + [Key] + public int Id { get; set; } + [Required, StringLength(100)] + public string Name { get; set; } + [Required, StringLength(500), DataType(DataType.MultilineText)] + public string Description { get; set; } + [Required, StringLength(25)] + public string Icon { get; set; } + [Required, StringLength(10)] + public string IconColour { get; set; } + + public int? DefaultSLAExpiry { get; set; } + [Required] + public JobQueuePriority Priority { get; set; } + + public string SubjectIds { get; set; } + + public virtual IList JobSubTypes { get; set; } + + public virtual IList QueueJobs { get; set; } + + public override string ToString() + { + return this.Name; + } + } +} diff --git a/Disco.Models/Repository/Job/Queue/JobQueueJob.cs b/Disco.Models/Repository/Job/Queue/JobQueueJob.cs new file mode 100644 index 00000000..c574a70b --- /dev/null +++ b/Disco.Models/Repository/Job/Queue/JobQueueJob.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Models.Repository +{ + public class JobQueueJob + { + public int Id { get; set; } + + [Required] + public int JobQueueId { get; set; } + [Required] + public int JobId { get; set; } + + [Required] + public DateTime AddedDate { get; set; } + [Required] + public string AddedUserId { get; set; } + public string AddedComment { get; set; } + + public DateTime? RemovedDate { get; set; } + public string RemovedUserId { get; set; } + public string RemovedComment { get; set; } + + public DateTime? SLAExpiresDate { get; set; } + public JobQueuePriority Priority { get; set; } + + [ForeignKey("JobQueueId")] + public virtual JobQueue JobQueue { get; set; } + [ForeignKey("JobId")] + public virtual Job Job { get; set; } + [ForeignKey("AddedUserId")] + public virtual User AddedUser { get; set; } + [ForeignKey("RemovedUserId")] + public virtual User RemovedUser { get; set; } + } +} diff --git a/Disco.Models/Repository/Job/Queue/JobQueuePriority.cs b/Disco.Models/Repository/Job/Queue/JobQueuePriority.cs new file mode 100644 index 00000000..db4e17ff --- /dev/null +++ b/Disco.Models/Repository/Job/Queue/JobQueuePriority.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Models.Repository +{ + public enum JobQueuePriority : byte + { + High = 2, + Normal = 1, + Low = 0 + } +} diff --git a/Disco.Models/Authorization/IAuthorizationToken.cs b/Disco.Models/Services/Authorization/IAuthorizationToken.cs similarity index 84% rename from Disco.Models/Authorization/IAuthorizationToken.cs rename to Disco.Models/Services/Authorization/IAuthorizationToken.cs index 39ef4e4f..1fa86a3f 100644 --- a/Disco.Models/Authorization/IAuthorizationToken.cs +++ b/Disco.Models/Services/Authorization/IAuthorizationToken.cs @@ -1,11 +1,7 @@ using Disco.Models.Repository; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace Disco.Models.Authorization +namespace Disco.Models.Services.Authorization { public interface IAuthorizationToken { diff --git a/Disco.Models/Authorization/IClaimNavigatorItem.cs b/Disco.Models/Services/Authorization/IClaimNavigatorItem.cs similarity index 65% rename from Disco.Models/Authorization/IClaimNavigatorItem.cs rename to Disco.Models/Services/Authorization/IClaimNavigatorItem.cs index 1900869a..b4f6b858 100644 --- a/Disco.Models/Authorization/IClaimNavigatorItem.cs +++ b/Disco.Models/Services/Authorization/IClaimNavigatorItem.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; -namespace Disco.Models.Authorization +namespace Disco.Models.Services.Authorization { public interface IClaimNavigatorItem { diff --git a/Disco.Models/Authorization/IRoleToken.cs b/Disco.Models/Services/Authorization/IRoleToken.cs similarity index 63% rename from Disco.Models/Authorization/IRoleToken.cs rename to Disco.Models/Services/Authorization/IRoleToken.cs index a209e3bf..a80481fa 100644 --- a/Disco.Models/Authorization/IRoleToken.cs +++ b/Disco.Models/Services/Authorization/IRoleToken.cs @@ -1,11 +1,7 @@ using Disco.Models.Repository; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace Disco.Models.Authorization +namespace Disco.Models.Services.Authorization { public interface IRoleToken { diff --git a/Disco.Models/Services/Jobs/JobLists/JobTableItemModel.cs b/Disco.Models/Services/Jobs/JobLists/JobTableItemModel.cs new file mode 100644 index 00000000..08a058bb --- /dev/null +++ b/Disco.Models/Services/Jobs/JobLists/JobTableItemModel.cs @@ -0,0 +1,27 @@ +using System; + +namespace Disco.Models.Services.Jobs.JobLists +{ + public class JobTableItemModel + { + public int Id { get; set; } + public DateTime OpenedDate { get; set; } + public DateTime? ClosedDate { get; set; } + public string JobTypeId { get; set; } + public string JobTypeDescription { get; set; } + public string DeviceSerialNumber { get; set; } + public int? DeviceModelId { get; set; } + public string DeviceModelDescription { get; set; } + public int? DeviceProfileId { get; set; } + public int? DeviceAddressId { get; set; } + public string DeviceAddress { get; set; } + public string UserId { get; set; } + public string UserDisplayName { get; set; } + public string OpenedTechUserId { get; set; } + public string OpenedTechUserDisplayName { get; set; } + public string StatusDescription { get; set; } + public string StatusId { get; set; } + public string DeviceHeldLocation { get; set; } + public Disco.Models.Repository.Job.UserManagementFlags? Flags { get; set; } + } +} diff --git a/Disco.Models/Services/Jobs/JobLists/JobTableModel.cs b/Disco.Models/Services/Jobs/JobLists/JobTableModel.cs new file mode 100644 index 00000000..11809042 --- /dev/null +++ b/Disco.Models/Services/Jobs/JobLists/JobTableModel.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; + +namespace Disco.Models.Services.Jobs.JobLists +{ + public class JobTableModel + { + public bool ShowId { get; set; } + public bool? ShowDeviceAddress { get; set; } + public bool ShowDates { get; set; } + public bool ShowType { get; set; } + public bool ShowDevice { get; set; } + public bool ShowUser { get; set; } + public bool ShowTechnician { get; set; } + public bool ShowLocation { get; set; } + public bool ShowStatus { get; set; } + + public bool IsSmallTable { get; set; } + public bool HideClosedJobs { get; set; } + public bool EnablePaging { get; set; } + public bool EnableFilter { get; set; } + + public virtual IEnumerable Items { get; set; } + + public JobTableModel() + { + ShowId = true; + ShowDates = true; + ShowType = true; + ShowDevice = true; + ShowUser = true; + ShowTechnician = true; + EnablePaging = true; + EnableFilter = true; + } + } +} diff --git a/Disco.Models/Services/Jobs/JobLists/JobTableStatusItemModel.cs b/Disco.Models/Services/Jobs/JobLists/JobTableStatusItemModel.cs new file mode 100644 index 00000000..963de397 --- /dev/null +++ b/Disco.Models/Services/Jobs/JobLists/JobTableStatusItemModel.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; + +namespace Disco.Models.Services.Jobs.JobLists +{ + public class JobTableStatusItemModel : JobTableItemModel + { + public string JobMetaWarranty_ExternalReference { get; set; } + public DateTime? JobMetaWarranty_ExternalLoggedDate { get; set; } + public DateTime? JobMetaWarranty_ExternalCompletedDate { get; set; } + + public DateTime? JobMetaNonWarranty_RepairerLoggedDate { get; set; } + public DateTime? JobMetaNonWarranty_RepairerCompletedDate { get; set; } + public DateTime? JobMetaNonWarranty_AccountingChargeAddedDate { get; set; } + public DateTime? JobMetaNonWarranty_AccountingChargePaidDate { get; set; } + public DateTime? JobMetaNonWarranty_AccountingChargeRequiredDate { get; set; } + public bool? JobMetaNonWarranty_IsInsuranceClaim { get; set; } + public DateTime? JobMetaInsurance_ClaimFormSentDate { get; set; } + + public DateTime? WaitingForUserAction { get; set; } + public DateTime? DeviceReadyForReturn { get; set; } + public DateTime? DeviceHeld { get; set; } + public DateTime? DeviceReturnedDate { get; set; } + public string JobMetaWarranty_ExternalName { get; set; } + public string JobMetaNonWarranty_RepairerName { get; set; } + + public IEnumerable ActiveJobQueues { get; set; } + } +} diff --git a/Disco.Models/Services/Jobs/JobLists/JobTableStatusQueueItemModel.cs b/Disco.Models/Services/Jobs/JobLists/JobTableStatusQueueItemModel.cs new file mode 100644 index 00000000..1aa50a39 --- /dev/null +++ b/Disco.Models/Services/Jobs/JobLists/JobTableStatusQueueItemModel.cs @@ -0,0 +1,14 @@ +using Disco.Models.Repository; +using System; + +namespace Disco.Models.Services.Jobs.JobLists +{ + public class JobTableStatusQueueItemModel + { + public int Id { get; set; } + public int QueueId { get; set; } + public DateTime AddedDate { get; set; } + public DateTime? SLAExpiresDate { get; set; } + public JobQueuePriority Priority { get; set; } + } +} diff --git a/Disco.Models/Services/Jobs/JobQueues/IJobQueueToken.cs b/Disco.Models/Services/Jobs/JobQueues/IJobQueueToken.cs new file mode 100644 index 00000000..8837f541 --- /dev/null +++ b/Disco.Models/Services/Jobs/JobQueues/IJobQueueToken.cs @@ -0,0 +1,11 @@ +using Disco.Models.Repository; +using System.Collections.ObjectModel; + +namespace Disco.Models.Services.Jobs.JobQueues +{ + public interface IJobQueueToken + { + JobQueue JobQueue { get; } + ReadOnlyCollection SubjectIds { get; } + } +} \ No newline at end of file diff --git a/Disco.Models/UI/Config/AuthorizationRole/ConfigAuthorizationRoleIndexModel.cs b/Disco.Models/UI/Config/AuthorizationRole/ConfigAuthorizationRoleIndexModel.cs index f0ee1e97..74a96805 100644 --- a/Disco.Models/UI/Config/AuthorizationRole/ConfigAuthorizationRoleIndexModel.cs +++ b/Disco.Models/UI/Config/AuthorizationRole/ConfigAuthorizationRoleIndexModel.cs @@ -1,4 +1,4 @@ -using Disco.Models.Authorization; +using Disco.Models.Services.Authorization; using System; using System.Collections.Generic; using System.Linq; diff --git a/Disco.Models/UI/Config/AuthorizationRole/ConfigAuthorizationRoleShowModel.cs b/Disco.Models/UI/Config/AuthorizationRole/ConfigAuthorizationRoleShowModel.cs index e3aa4b9b..6d00a7b8 100644 --- a/Disco.Models/UI/Config/AuthorizationRole/ConfigAuthorizationRoleShowModel.cs +++ b/Disco.Models/UI/Config/AuthorizationRole/ConfigAuthorizationRoleShowModel.cs @@ -1,4 +1,4 @@ -using Disco.Models.Authorization; +using Disco.Models.Services.Authorization; using System; using System.Collections.Generic; using System.Linq; diff --git a/Disco.Models/UI/Config/DocumentTemplate/ConfigDocumentTemplateShowModel.cs b/Disco.Models/UI/Config/DocumentTemplate/ConfigDocumentTemplateShowModel.cs index 148cb03b..e91fe8b5 100644 --- a/Disco.Models/UI/Config/DocumentTemplate/ConfigDocumentTemplateShowModel.cs +++ b/Disco.Models/UI/Config/DocumentTemplate/ConfigDocumentTemplateShowModel.cs @@ -11,11 +11,7 @@ namespace Disco.Models.UI.Config.DocumentTemplate Disco.Models.Repository.DocumentTemplate DocumentTemplate { get; set; } int StoredInstanceCount { get; set; } - List Types { get; set; } - List SubTypes { get; set; } - List JobTypes { get; set; } - List JobSubTypes { get; set; } List Scopes { get; } } diff --git a/Disco.Models/UI/Config/JobQueue/ConfigJobQueueCreateModel.cs b/Disco.Models/UI/Config/JobQueue/ConfigJobQueueCreateModel.cs new file mode 100644 index 00000000..473ed2ba --- /dev/null +++ b/Disco.Models/UI/Config/JobQueue/ConfigJobQueueCreateModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Models.UI.Config.JobQueue +{ + public interface ConfigJobQueueCreateModel : BaseUIModel + { + Repository.JobQueue JobQueue { get; set; } + } +} diff --git a/Disco.Models/UI/Config/JobQueue/ConfigJobQueueIndexModel.cs b/Disco.Models/UI/Config/JobQueue/ConfigJobQueueIndexModel.cs new file mode 100644 index 00000000..087c4579 --- /dev/null +++ b/Disco.Models/UI/Config/JobQueue/ConfigJobQueueIndexModel.cs @@ -0,0 +1,14 @@ +using Disco.Models.Services.Jobs.JobQueues; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Models.UI.Config.JobQueue +{ + public interface ConfigJobQueueIndexModel : BaseUIModel + { + List Tokens { get; set; } + } +} diff --git a/Disco.Models/UI/Config/JobQueue/ConfigJobQueueShowModel.cs b/Disco.Models/UI/Config/JobQueue/ConfigJobQueueShowModel.cs new file mode 100644 index 00000000..013ac969 --- /dev/null +++ b/Disco.Models/UI/Config/JobQueue/ConfigJobQueueShowModel.cs @@ -0,0 +1,21 @@ +using Disco.Models.Services.Jobs.JobQueues; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Models.UI.Config.JobQueue +{ + public interface ConfigJobQueueShowModel : BaseUIModel + { + IJobQueueToken Token { get; set; } + + int OpenJobCount { get; set; } + int TotalJobCount { get; set; } + + List JobTypes { get; set; } + + bool CanDelete { get; set; } + } +} diff --git a/Disco.Models/UI/Device/DeviceShowModel.cs b/Disco.Models/UI/Device/DeviceShowModel.cs index d62d8fc4..10739446 100644 --- a/Disco.Models/UI/Device/DeviceShowModel.cs +++ b/Disco.Models/UI/Device/DeviceShowModel.cs @@ -1,8 +1,5 @@ -using System; +using Disco.Models.Services.Jobs.JobLists; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Disco.Models.UI.Device { @@ -15,7 +12,7 @@ namespace Disco.Models.UI.Device List DeviceBatches { get; set; } - Disco.Models.BI.Job.JobTableModel Jobs { get; set; } + JobTableModel Jobs { get; set; } List Certificates { get; set; } diff --git a/Disco.Models/UI/Job/JobCreateModel.cs b/Disco.Models/UI/Job/JobCreateModel.cs index 4302d2f1..87d52d62 100644 --- a/Disco.Models/UI/Job/JobCreateModel.cs +++ b/Disco.Models/UI/Job/JobCreateModel.cs @@ -28,6 +28,5 @@ namespace Disco.Models.UI.Job Disco.Models.Repository.Device Device { get; set; } Disco.Models.Repository.User User { get; set; } List JobTypes { get; set; } - List JobSubTypes { get; set; } } } diff --git a/Disco.Models/UI/Job/JobIndexModel.cs b/Disco.Models/UI/Job/JobIndexModel.cs index 02d558b2..c468b447 100644 --- a/Disco.Models/UI/Job/JobIndexModel.cs +++ b/Disco.Models/UI/Job/JobIndexModel.cs @@ -1,15 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Disco.Models.BI.Job; +using Disco.Models.Services.Jobs.JobLists; namespace Disco.Models.UI.Job { public interface JobIndexModel : BaseUIModel { - JobTableModel OpenJobs { get; set; } + JobTableModel MyJobs { get; set; } JobTableModel LongRunningJobs { get; set; } } } diff --git a/Disco.Models/UI/Job/JobListModel.cs b/Disco.Models/UI/Job/JobListModel.cs index 09e56d18..2f5e8526 100644 --- a/Disco.Models/UI/Job/JobListModel.cs +++ b/Disco.Models/UI/Job/JobListModel.cs @@ -1,14 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Disco.Models.Services.Jobs.JobLists; namespace Disco.Models.UI.Job { public interface JobListModel : BaseUIModel { string Title { get; set; } - Disco.Models.BI.Job.JobTableModel JobTable { get; set; } + JobTableModel JobTable { get; set; } } -} +} \ No newline at end of file diff --git a/Disco.Models/UI/Job/JobShowModel.cs b/Disco.Models/UI/Job/JobShowModel.cs index c19e39f0..79c2469a 100644 --- a/Disco.Models/UI/Job/JobShowModel.cs +++ b/Disco.Models/UI/Job/JobShowModel.cs @@ -12,5 +12,6 @@ namespace Disco.Models.UI.Job TimeSpan? LongRunning { get; set; } List AvailableDocumentTemplates { get; set; } List UpdatableJobSubTypes { get; set; } + List AvailableQueues { get; set; } } } diff --git a/Disco.Models/UI/Search/SearchQueryModel.cs b/Disco.Models/UI/Search/SearchQueryModel.cs index e9db0072..470efdc6 100644 --- a/Disco.Models/UI/Search/SearchQueryModel.cs +++ b/Disco.Models/UI/Search/SearchQueryModel.cs @@ -1,8 +1,6 @@ -using System; +using Disco.Models.BI.Search; +using Disco.Models.Services.Jobs.JobLists; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Disco.Models.UI.Search { @@ -12,8 +10,8 @@ namespace Disco.Models.UI.Search string Term { get; set; } bool Success { get; set; } string ErrorMessage { get; set; } - List Devices { get; set; } - Disco.Models.BI.Job.JobTableModel Jobs { get; set; } - List Users { get; set; } + List Devices { get; set; } + JobTableModel Jobs { get; set; } + List Users { get; set; } } } diff --git a/Disco.Models/UI/User/UserShowModel.cs b/Disco.Models/UI/User/UserShowModel.cs index a245de25..5c257253 100644 --- a/Disco.Models/UI/User/UserShowModel.cs +++ b/Disco.Models/UI/User/UserShowModel.cs @@ -1,18 +1,15 @@ -using Disco.Models.Authorization; -using System; +using Disco.Models.Services.Authorization; +using Disco.Models.Services.Jobs.JobLists; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Disco.Models.UI.User { public interface UserShowModel : BaseUIModel { Disco.Models.Repository.User User { get; set; } - Disco.Models.BI.Job.JobTableModel Jobs { get; set; } + JobTableModel Jobs { get; set; } List DocumentTemplates { get; set; } IAuthorizationToken AuthorizationToken { get; set; } IClaimNavigatorItem ClaimNavigator { get; set; } } -} +} \ No newline at end of file diff --git a/Disco.Services/Authorization/AuthorizationToken.cs b/Disco.Services/Authorization/AuthorizationToken.cs index b1ccd4c6..2e8cd130 100644 --- a/Disco.Services/Authorization/AuthorizationToken.cs +++ b/Disco.Services/Authorization/AuthorizationToken.cs @@ -1,4 +1,4 @@ -using Disco.Models.Authorization; +using Disco.Models.Services.Authorization; using Disco.Models.Repository; using Disco.Services.Authorization.Roles; using System; diff --git a/Disco.Services/Authorization/ClaimNavigatorItem.cs b/Disco.Services/Authorization/ClaimNavigatorItem.cs index e33cff5f..5590c386 100644 --- a/Disco.Services/Authorization/ClaimNavigatorItem.cs +++ b/Disco.Services/Authorization/ClaimNavigatorItem.cs @@ -1,4 +1,4 @@ -using Disco.Models.Authorization; +using Disco.Models.Services.Authorization; using Disco.Services.Authorization.Roles; using System; using System.Collections.Generic; diff --git a/Disco.Services/Authorization/Claims.cs b/Disco.Services/Authorization/Claims.cs index a9534e4b..6ec2fc3c 100644 --- a/Disco.Services/Authorization/Claims.cs +++ b/Disco.Services/Authorization/Claims.cs @@ -5,7 +5,7 @@ // 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. -using Disco.Models.Authorization; +using Disco.Models.Services.Authorization; using Disco.Models.Repository; using Disco.Services.Authorization.Roles; using System; @@ -68,6 +68,10 @@ namespace Disco.Services.Authorization { "Config.Organisation.Show", new Tuple, Action, string, string, bool>(c => c.Config.Organisation.Show, (c, v) => c.Config.Organisation.Show = v, "Show Organisation Details", "Can show the organisation details", false) }, { "Config.JobPreferences.Configure", new Tuple, Action, string, string, bool>(c => c.Config.JobPreferences.Configure, (c, v) => c.Config.JobPreferences.Configure = v, "Configure Job Preferences", "Can configure job preferences", false) }, { "Config.JobPreferences.Show", new Tuple, Action, string, string, bool>(c => c.Config.JobPreferences.Show, (c, v) => c.Config.JobPreferences.Show = v, "Show Job Preferences", "Can show job preferences", false) }, + { "Config.JobQueue.Configure", new Tuple, Action, string, string, bool>(c => c.Config.JobQueue.Configure, (c, v) => c.Config.JobQueue.Configure = v, "Configure Job Queues", "Can configure job queues", false) }, + { "Config.JobQueue.Create", new Tuple, Action, string, string, bool>(c => c.Config.JobQueue.Create, (c, v) => c.Config.JobQueue.Create = v, "Create Job Queues", "Can create job queues", false) }, + { "Config.JobQueue.Delete", new Tuple, Action, string, string, bool>(c => c.Config.JobQueue.Delete, (c, v) => c.Config.JobQueue.Delete = v, "Delete Job Queues", "Can delete job queues", false) }, + { "Config.JobQueue.Show", new Tuple, Action, string, string, bool>(c => c.Config.JobQueue.Show, (c, v) => c.Config.JobQueue.Show = v, "Show Job Queues", "Can show job queues", false) }, { "Config.Show", new Tuple, Action, string, string, bool>(c => c.Config.Show, (c, v) => c.Config.Show = v, "Show Configuration", "Can show the configuration menu", false) }, { "Job.Lists.AllOpen", new Tuple, Action, string, string, bool>(c => c.Job.Lists.AllOpen, (c, v) => c.Job.Lists.AllOpen = v, "All Open List", "Can show list", false) }, { "Job.Lists.AwaitingFinanceAgreementBreach", new Tuple, Action, string, string, bool>(c => c.Job.Lists.AwaitingFinanceAgreementBreach, (c, v) => c.Job.Lists.AwaitingFinanceAgreementBreach = v, "Awaiting Finance Agreement Breach List", "Can show list (NOTE: Requires Awaiting Finance List)", false) }, @@ -79,11 +83,16 @@ namespace Disco.Services.Authorization { "Job.Lists.AwaitingUserAction", new Tuple, Action, string, string, bool>(c => c.Job.Lists.AwaitingUserAction, (c, v) => c.Job.Lists.AwaitingUserAction = v, "Awaiting User Action List", "Can show list", false) }, { "Job.Lists.DevicesAwaitingRepair", new Tuple, Action, string, string, bool>(c => c.Job.Lists.DevicesAwaitingRepair, (c, v) => c.Job.Lists.DevicesAwaitingRepair = v, "Devices Awaiting Repair List", "Can show list", false) }, { "Job.Lists.DevicesReadyForReturn", new Tuple, Action, string, string, bool>(c => c.Job.Lists.DevicesReadyForReturn, (c, v) => c.Job.Lists.DevicesReadyForReturn = v, "Devices Ready For Return List", "Can show list", false) }, + { "Job.Lists.JobQueueLists", new Tuple, Action, string, string, bool>(c => c.Job.Lists.JobQueueLists, (c, v) => c.Job.Lists.JobQueueLists = v, "Job Queue Lists", "Can show job queue lists", false) }, { "Job.Lists.Locations", new Tuple, Action, string, string, bool>(c => c.Job.Lists.Locations, (c, v) => c.Job.Lists.Locations = v, "Locations List", "Can show list", false) }, { "Job.Lists.LongRunningJobs", new Tuple, Action, string, string, bool>(c => c.Job.Lists.LongRunningJobs, (c, v) => c.Job.Lists.LongRunningJobs = v, "Long Running Jobs List", "Can show list", false) }, + { "Job.Lists.MyJobs", new Tuple, Action, string, string, bool>(c => c.Job.Lists.MyJobs, (c, v) => c.Job.Lists.MyJobs = v, "My Jobs List", "Can show list", false) }, + { "Job.Lists.MyJobsOrphaned", new Tuple, Action, string, string, bool>(c => c.Job.Lists.MyJobsOrphaned, (c, v) => c.Job.Lists.MyJobsOrphaned = v, "My Jobs List (Includes No Queue)", "Can show list", false) }, { "Job.Lists.RecentlyClosed", new Tuple, Action, string, string, bool>(c => c.Job.Lists.RecentlyClosed, (c, v) => c.Job.Lists.RecentlyClosed = v, "Recently Closed List", "Can show list", false) }, { "Job.Actions.AddAttachments", new Tuple, Action, string, string, bool>(c => c.Job.Actions.AddAttachments, (c, v) => c.Job.Actions.AddAttachments = v, "Add Attachments", "Can add attachments to jobs", false) }, { "Job.Actions.AddLogs", new Tuple, Action, string, string, bool>(c => c.Job.Actions.AddLogs, (c, v) => c.Job.Actions.AddLogs = v, "Add Logs", "Can add job logs", false) }, + { "Job.Actions.AddAnyQueues", new Tuple, Action, string, string, bool>(c => c.Job.Actions.AddAnyQueues, (c, v) => c.Job.Actions.AddAnyQueues = v, "Add to Any Queues", "Can add to any job queues", false) }, + { "Job.Actions.AddOwnQueues", new Tuple, Action, string, string, bool>(c => c.Job.Actions.AddOwnQueues, (c, v) => c.Job.Actions.AddOwnQueues = v, "Add to Own Queues", "Can add to own job queues", false) }, { "Job.Actions.Close", new Tuple, Action, string, string, bool>(c => c.Job.Actions.Close, (c, v) => c.Job.Actions.Close = v, "Close Jobs", "Can close jobs", false) }, { "Job.Actions.ConvertHWarToHNWar", new Tuple, Action, string, string, bool>(c => c.Job.Actions.ConvertHWarToHNWar, (c, v) => c.Job.Actions.ConvertHWarToHNWar = v, "Convert HWar Jobs To HNWar", "Can convert warranty jobs to non-warranty jobs", false) }, { "Job.Actions.Create", new Tuple, Action, string, string, bool>(c => c.Job.Actions.Create, (c, v) => c.Job.Actions.Create = v, "Create Jobs", "Can create jobs", false) }, @@ -94,6 +103,8 @@ namespace Disco.Services.Authorization { "Job.Actions.LogWarranty", new Tuple, Action, 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, Action, 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.RemoveAnyLogs", new Tuple, Action, string, string, bool>(c => c.Job.Actions.RemoveAnyLogs, (c, v) => c.Job.Actions.RemoveAnyLogs = v, "Remove Any Logs", "Can remove any job logs", false) }, + { "Job.Actions.RemoveAnyQueues", new Tuple, Action, string, string, bool>(c => c.Job.Actions.RemoveAnyQueues, (c, v) => c.Job.Actions.RemoveAnyQueues = v, "Remove from Any Queues", "Can remove from any job queues", false) }, + { "Job.Actions.RemoveOwnQueues", new Tuple, Action, string, string, bool>(c => c.Job.Actions.RemoveOwnQueues, (c, v) => c.Job.Actions.RemoveOwnQueues = v, "Remove from Own Queues", "Can remove from own job queues", false) }, { "Job.Actions.RemoveOwnAttachments", new Tuple, Action, string, string, bool>(c => c.Job.Actions.RemoveOwnAttachments, (c, v) => c.Job.Actions.RemoveOwnAttachments = v, "Remove Own Attachments", "Can remove own attachments from jobs", false) }, { "Job.Actions.RemoveOwnLogs", new Tuple, Action, string, string, bool>(c => c.Job.Actions.RemoveOwnLogs, (c, v) => c.Job.Actions.RemoveOwnLogs = v, "Remove Own Logs", "Can remove own job logs", false) }, { "Job.Actions.Reopen", new Tuple, Action, string, string, bool>(c => c.Job.Actions.Reopen, (c, v) => c.Job.Actions.Reopen = v, "Reopen Jobs", "Can reopen jobs", false) }, @@ -120,6 +131,12 @@ namespace Disco.Services.Authorization { "Job.Properties.NonWarrantyProperties.RepairerLoggedDate", new Tuple, Action, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairerLoggedDate, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairerLoggedDate = v, "Repairer Logged Date Property", "Can update property", false) }, { "Job.Properties.NonWarrantyProperties.RepairerName", new Tuple, Action, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairerName, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairerName = v, "Repairer Name Property", "Can update property", false) }, { "Job.Properties.NonWarrantyProperties.RepairerReference", new Tuple, Action, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairerReference, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairerReference = v, "Repairer Reference Property", "Can update property", false) }, + { "Job.Properties.JobQueueProperties.EditAnyComments", new Tuple, Action, string, string, bool>(c => c.Job.Properties.JobQueueProperties.EditAnyComments, (c, v) => c.Job.Properties.JobQueueProperties.EditAnyComments = v, "Edit Any Comments", "Can edit any job queue comments", false) }, + { "Job.Properties.JobQueueProperties.EditAnyPriority", new Tuple, Action, string, string, bool>(c => c.Job.Properties.JobQueueProperties.EditAnyPriority, (c, v) => c.Job.Properties.JobQueueProperties.EditAnyPriority = v, "Edit Any Priority", "Can edit any job queue Priority", false) }, + { "Job.Properties.JobQueueProperties.EditAnySLA", new Tuple, Action, string, string, bool>(c => c.Job.Properties.JobQueueProperties.EditAnySLA, (c, v) => c.Job.Properties.JobQueueProperties.EditAnySLA = v, "Edit Any SLA", "Can edit any job queue SLA", false) }, + { "Job.Properties.JobQueueProperties.EditOwnComments", new Tuple, Action, string, string, bool>(c => c.Job.Properties.JobQueueProperties.EditOwnComments, (c, v) => c.Job.Properties.JobQueueProperties.EditOwnComments = v, "Edit Own Comments", "Can edit own job queue comments", false) }, + { "Job.Properties.JobQueueProperties.EditOwnPriority", new Tuple, Action, string, string, bool>(c => c.Job.Properties.JobQueueProperties.EditOwnPriority, (c, v) => c.Job.Properties.JobQueueProperties.EditOwnPriority = v, "Edit Own Priority", "Can edit own job queue Priority", false) }, + { "Job.Properties.JobQueueProperties.EditOwnSLA", new Tuple, Action, string, string, bool>(c => c.Job.Properties.JobQueueProperties.EditOwnSLA, (c, v) => c.Job.Properties.JobQueueProperties.EditOwnSLA = v, "Edit Own SLA", "Can edit own job queue SLA", false) }, { "Job.Properties.DeviceHeldLocation", new Tuple, Action, string, string, bool>(c => c.Job.Properties.DeviceHeldLocation, (c, v) => c.Job.Properties.DeviceHeldLocation = v, "Device Held Location Property", "Can update property", false) }, { "Job.Properties.DeviceHeld", new Tuple, Action, string, string, bool>(c => c.Job.Properties.DeviceHeld, (c, v) => c.Job.Properties.DeviceHeld = v, "Device Held Property", "Can update property", false) }, { "Job.Properties.DeviceReadyForReturn", new Tuple, Action, string, string, bool>(c => c.Job.Properties.DeviceReadyForReturn, (c, v) => c.Job.Properties.DeviceReadyForReturn = v, "Device Ready For Return Property", "Can update property", false) }, @@ -140,6 +157,7 @@ namespace Disco.Services.Authorization { "Job.ShowDailyChart", new Tuple, Action, string, string, bool>(c => c.Job.ShowDailyChart, (c, v) => c.Job.ShowDailyChart = v, "Show Daily Opened & Closed", "Can show daily opened & closed chart", false) }, { "Job.ShowFlags", new Tuple, Action, string, string, bool>(c => c.Job.ShowFlags, (c, v) => c.Job.ShowFlags = v, "Show Flags", "Can show job flags", false) }, { "Job.Show", new Tuple, Action, string, string, bool>(c => c.Job.Show, (c, v) => c.Job.Show = v, "Show Jobs", "Can show jobs", false) }, + { "Job.ShowJobsQueues", new Tuple, Action, string, string, bool>(c => c.Job.ShowJobsQueues, (c, v) => c.Job.ShowJobsQueues = v, "Show Jobs Queues", "Can show jobs queues", false) }, { "Job.ShowLogs", new Tuple, Action, string, string, bool>(c => c.Job.ShowLogs, (c, v) => c.Job.ShowLogs = v, "Show Logs", "Can show job logs", false) }, { "Job.ShowNonWarrantyComponents", new Tuple, Action, string, string, bool>(c => c.Job.ShowNonWarrantyComponents, (c, v) => c.Job.ShowNonWarrantyComponents = v, "Show Non-Warranty Components", "Can show non-warranty job components", false) }, { "Job.ShowNonWarrantyFinance", new Tuple, Action, string, string, bool>(c => c.Job.ShowNonWarrantyFinance, (c, v) => c.Job.ShowNonWarrantyFinance = v, "Show Non-Warranty Finance", "Can show non-warranty job finance", false) }, @@ -189,29 +207,23 @@ namespace Disco.Services.Authorization _claimNavigator = new ClaimNavigatorItem("Claims", "Permissions", "Top-level node for all permissions", false, new List() { new ClaimNavigatorItem("Config", "Configuration", "Permissions related to Disco Configuration", false, new List() { - new ClaimNavigatorItem("Config.DeviceCertificate", "Device Certificate", "Permissions related to Device Certificates", false, new List() { - new ClaimNavigatorItem("Config.DeviceCertificate.DownloadCertificates", false) - }), - new ClaimNavigatorItem("Config.Enrolment", "Enrolment", "Permissions related to Device Enrolment", false, new List() { - new ClaimNavigatorItem("Config.Enrolment.Configure", false), - new ClaimNavigatorItem("Config.Enrolment.DownloadBootstrapper", false), - new ClaimNavigatorItem("Config.Enrolment.Show", false), - new ClaimNavigatorItem("Config.Enrolment.ShowStatus", false) - }), - new ClaimNavigatorItem("Config.DeviceBatch", "Device Batch", "Permissions related to Device Batches", false, new List() { + new ClaimNavigatorItem("Config.DeviceBatch", "Device Batches", "Permissions related to Device Batches", false, new List() { new ClaimNavigatorItem("Config.DeviceBatch.Configure", false), new ClaimNavigatorItem("Config.DeviceBatch.Create", false), new ClaimNavigatorItem("Config.DeviceBatch.Delete", false), new ClaimNavigatorItem("Config.DeviceBatch.Show", false), new ClaimNavigatorItem("Config.DeviceBatch.ShowTimeline", false) }), - new ClaimNavigatorItem("Config.DeviceModel", "Device Model", "Permissions related to Device Models", false, new List() { + new ClaimNavigatorItem("Config.DeviceCertificate", "Device Certificates", "Permissions related to Device Certificates", false, new List() { + new ClaimNavigatorItem("Config.DeviceCertificate.DownloadCertificates", false) + }), + new ClaimNavigatorItem("Config.DeviceModel", "Device Models", "Permissions related to Device Models", false, new List() { new ClaimNavigatorItem("Config.DeviceModel.ConfigureComponents", false), new ClaimNavigatorItem("Config.DeviceModel.Configure", false), new ClaimNavigatorItem("Config.DeviceModel.Delete", false), new ClaimNavigatorItem("Config.DeviceModel.Show", false) }), - new ClaimNavigatorItem("Config.DeviceProfile", "Device Profile", "Permissions related to Device Profiles", false, new List() { + new ClaimNavigatorItem("Config.DeviceProfile", "Device Profiles", "Permissions related to Device Profiles", false, new List() { new ClaimNavigatorItem("Config.DeviceProfile.ConfigureComputerNameTemplate", false), new ClaimNavigatorItem("Config.DeviceProfile.ConfigureDefaults", false), new ClaimNavigatorItem("Config.DeviceProfile.Configure", false), @@ -219,7 +231,7 @@ namespace Disco.Services.Authorization new ClaimNavigatorItem("Config.DeviceProfile.Delete", false), new ClaimNavigatorItem("Config.DeviceProfile.Show", false) }), - new ClaimNavigatorItem("Config.DocumentTemplate", "Document Template", "Permissions related to Document Templates", false, new List() { + new ClaimNavigatorItem("Config.DocumentTemplate", "Document Templates", "Permissions related to Document Templates", false, new List() { new ClaimNavigatorItem("Config.DocumentTemplate.BulkGenerate", false), new ClaimNavigatorItem("Config.DocumentTemplate.Configure", false), new ClaimNavigatorItem("Config.DocumentTemplate.ConfigureFilterExpression", false), @@ -230,20 +242,25 @@ namespace Disco.Services.Authorization new ClaimNavigatorItem("Config.DocumentTemplate.UndetectedPages", false), new ClaimNavigatorItem("Config.DocumentTemplate.Upload", false) }), + new ClaimNavigatorItem("Config.Enrolment", "Enrolment", "Permissions related to Device Enrolment", false, new List() { + new ClaimNavigatorItem("Config.Enrolment.Configure", false), + new ClaimNavigatorItem("Config.Enrolment.DownloadBootstrapper", false), + new ClaimNavigatorItem("Config.Enrolment.Show", false), + new ClaimNavigatorItem("Config.Enrolment.ShowStatus", false) + }), + new ClaimNavigatorItem("Config.JobPreferences", "Job Preferences", "Permissions related to Job Preferences", false, new List() { + new ClaimNavigatorItem("Config.JobPreferences.Configure", false), + new ClaimNavigatorItem("Config.JobPreferences.Show", false) + }), + new ClaimNavigatorItem("Config.JobQueue", "Job Queues", "Permissions related to Job Queues", false, new List() { + new ClaimNavigatorItem("Config.JobQueue.Configure", false), + new ClaimNavigatorItem("Config.JobQueue.Create", false), + new ClaimNavigatorItem("Config.JobQueue.Delete", false), + new ClaimNavigatorItem("Config.JobQueue.Show", false) + }), new ClaimNavigatorItem("Config.Logging", "Logging", "Permissions related to Logging", false, new List() { new ClaimNavigatorItem("Config.Logging.Show", false) }), - new ClaimNavigatorItem("Config.Plugin", "Plugin", "Permissions related to Plugins", false, new List() { - new ClaimNavigatorItem("Config.Plugin.Configure", false), - new ClaimNavigatorItem("Config.Plugin.InstallLocal", false), - new ClaimNavigatorItem("Config.Plugin.Install", false), - new ClaimNavigatorItem("Config.Plugin.Show", false), - new ClaimNavigatorItem("Config.Plugin.Uninstall", false) - }), - new ClaimNavigatorItem("Config.System", "System", "Permissions related to System Configuration", false, new List() { - new ClaimNavigatorItem("Config.System.ConfigureProxy", false), - new ClaimNavigatorItem("Config.System.Show", false) - }), new ClaimNavigatorItem("Config.Organisation", "Organisation Details", "Permissions related to the Organisation Details", false, new List() { new ClaimNavigatorItem("Config.Organisation.ConfigureAddresses", false), new ClaimNavigatorItem("Config.Organisation.ConfigureLogo", false), @@ -251,31 +268,25 @@ namespace Disco.Services.Authorization new ClaimNavigatorItem("Config.Organisation.ConfigureName", false), new ClaimNavigatorItem("Config.Organisation.Show", false) }), - new ClaimNavigatorItem("Config.JobPreferences", "Job Preferences", "Permissions related to Job Preferences", false, new List() { - new ClaimNavigatorItem("Config.JobPreferences.Configure", false), - new ClaimNavigatorItem("Config.JobPreferences.Show", false) + new ClaimNavigatorItem("Config.Plugin", "Plugin", "Permissions related to Plugins", false, new List() { + new ClaimNavigatorItem("Config.Plugin.Configure", false), + new ClaimNavigatorItem("Config.Plugin.InstallLocal", false), + new ClaimNavigatorItem("Config.Plugin.Install", false), + new ClaimNavigatorItem("Config.Plugin.Show", false), + new ClaimNavigatorItem("Config.Plugin.Uninstall", false) }), - new ClaimNavigatorItem("Config.Show", false) + new ClaimNavigatorItem("Config.Show", false), + new ClaimNavigatorItem("Config.System", "System", "Permissions related to System Configuration", false, new List() { + new ClaimNavigatorItem("Config.System.ConfigureProxy", false), + new ClaimNavigatorItem("Config.System.Show", false) + }) }), new ClaimNavigatorItem("Job", "Job", "Permissions related to Jobs", false, new List() { - new ClaimNavigatorItem("Job.Lists", "Lists", "Permissions related to Job Lists", false, new List() { - new ClaimNavigatorItem("Job.Lists.AllOpen", false), - new ClaimNavigatorItem("Job.Lists.AwaitingFinanceAgreementBreach", false), - new ClaimNavigatorItem("Job.Lists.AwaitingFinanceCharge", false), - new ClaimNavigatorItem("Job.Lists.AwaitingFinanceInsuranceProcessing", false), - new ClaimNavigatorItem("Job.Lists.AwaitingFinance", false), - new ClaimNavigatorItem("Job.Lists.AwaitingFinancePayment", false), - new ClaimNavigatorItem("Job.Lists.AwaitingTechnicianAction", false), - new ClaimNavigatorItem("Job.Lists.AwaitingUserAction", false), - new ClaimNavigatorItem("Job.Lists.DevicesAwaitingRepair", false), - new ClaimNavigatorItem("Job.Lists.DevicesReadyForReturn", false), - new ClaimNavigatorItem("Job.Lists.Locations", false), - new ClaimNavigatorItem("Job.Lists.LongRunningJobs", false), - new ClaimNavigatorItem("Job.Lists.RecentlyClosed", false) - }), new ClaimNavigatorItem("Job.Actions", "Actions", "Permissions related to Job Actions", false, new List() { new ClaimNavigatorItem("Job.Actions.AddAttachments", false), new ClaimNavigatorItem("Job.Actions.AddLogs", false), + new ClaimNavigatorItem("Job.Actions.AddAnyQueues", false), + new ClaimNavigatorItem("Job.Actions.AddOwnQueues", false), new ClaimNavigatorItem("Job.Actions.Close", false), new ClaimNavigatorItem("Job.Actions.ConvertHWarToHNWar", false), new ClaimNavigatorItem("Job.Actions.Create", false), @@ -286,19 +297,27 @@ namespace Disco.Services.Authorization new ClaimNavigatorItem("Job.Actions.LogWarranty", false), new ClaimNavigatorItem("Job.Actions.RemoveAnyAttachments", false), new ClaimNavigatorItem("Job.Actions.RemoveAnyLogs", false), + new ClaimNavigatorItem("Job.Actions.RemoveAnyQueues", false), + new ClaimNavigatorItem("Job.Actions.RemoveOwnQueues", false), new ClaimNavigatorItem("Job.Actions.RemoveOwnAttachments", false), new ClaimNavigatorItem("Job.Actions.RemoveOwnLogs", false), new ClaimNavigatorItem("Job.Actions.Reopen", false), new ClaimNavigatorItem("Job.Actions.UpdateSubTypes", false) }), new ClaimNavigatorItem("Job.Properties", "Job Properties", "Permissions related to Job Properties", false, new List() { - new ClaimNavigatorItem("Job.Properties.WarrantyProperties", "Warranty Properties", "Permissions related to Warranty Job Properties", false, new List() { - new ClaimNavigatorItem("Job.Properties.WarrantyProperties.ExternalCompletedDate", false), - new ClaimNavigatorItem("Job.Properties.WarrantyProperties.ExternalLoggedDate", false), - new ClaimNavigatorItem("Job.Properties.WarrantyProperties.ExternalName", false), - new ClaimNavigatorItem("Job.Properties.WarrantyProperties.ExternalReference", false), - new ClaimNavigatorItem("Job.Properties.WarrantyProperties.ProviderDetails", false), - new ClaimNavigatorItem("Job.Properties.WarrantyProperties.WarrantyCompleted", false) + new ClaimNavigatorItem("Job.Properties.DeviceHeldLocation", false), + new ClaimNavigatorItem("Job.Properties.DeviceHeld", false), + new ClaimNavigatorItem("Job.Properties.DeviceReadyForReturn", false), + new ClaimNavigatorItem("Job.Properties.DeviceReturned", false), + new ClaimNavigatorItem("Job.Properties.ExpectedClosedDate", false), + new ClaimNavigatorItem("Job.Properties.Flags", false), + new ClaimNavigatorItem("Job.Properties.JobQueueProperties", "Job Queue Properties", "Permissions related to Job Queue Job Properties", false, new List() { + new ClaimNavigatorItem("Job.Properties.JobQueueProperties.EditAnyComments", false), + new ClaimNavigatorItem("Job.Properties.JobQueueProperties.EditAnyPriority", false), + new ClaimNavigatorItem("Job.Properties.JobQueueProperties.EditAnySLA", false), + new ClaimNavigatorItem("Job.Properties.JobQueueProperties.EditOwnComments", false), + new ClaimNavigatorItem("Job.Properties.JobQueueProperties.EditOwnPriority", false), + new ClaimNavigatorItem("Job.Properties.JobQueueProperties.EditOwnSLA", false) }), new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties", "Non Warranty Properties", "Permissions related to Non-Warranty Job Properties", false, new List() { new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.AccountingChargeAdded", false), @@ -318,15 +337,47 @@ namespace Disco.Services.Authorization new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.RepairerName", false), new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.RepairerReference", false) }), - new ClaimNavigatorItem("Job.Properties.DeviceHeldLocation", false), - new ClaimNavigatorItem("Job.Properties.DeviceHeld", false), - new ClaimNavigatorItem("Job.Properties.DeviceReadyForReturn", false), - new ClaimNavigatorItem("Job.Properties.DeviceReturned", false), - new ClaimNavigatorItem("Job.Properties.ExpectedClosedDate", false), - new ClaimNavigatorItem("Job.Properties.Flags", false), new ClaimNavigatorItem("Job.Properties.NotWaitingForUserAction", false), - new ClaimNavigatorItem("Job.Properties.WaitingForUserAction", false) + new ClaimNavigatorItem("Job.Properties.WaitingForUserAction", false), + new ClaimNavigatorItem("Job.Properties.WarrantyProperties", "Warranty Properties", "Permissions related to Warranty Job Properties", false, new List() { + new ClaimNavigatorItem("Job.Properties.WarrantyProperties.ExternalCompletedDate", false), + new ClaimNavigatorItem("Job.Properties.WarrantyProperties.ExternalLoggedDate", false), + new ClaimNavigatorItem("Job.Properties.WarrantyProperties.ExternalName", false), + new ClaimNavigatorItem("Job.Properties.WarrantyProperties.ExternalReference", false), + new ClaimNavigatorItem("Job.Properties.WarrantyProperties.ProviderDetails", false), + new ClaimNavigatorItem("Job.Properties.WarrantyProperties.WarrantyCompleted", false) + }) }), + new ClaimNavigatorItem("Job.Lists", "Lists", "Permissions related to Job Lists", false, new List() { + new ClaimNavigatorItem("Job.Lists.AllOpen", false), + new ClaimNavigatorItem("Job.Lists.AwaitingFinanceAgreementBreach", false), + new ClaimNavigatorItem("Job.Lists.AwaitingFinanceCharge", false), + new ClaimNavigatorItem("Job.Lists.AwaitingFinanceInsuranceProcessing", false), + new ClaimNavigatorItem("Job.Lists.AwaitingFinance", false), + new ClaimNavigatorItem("Job.Lists.AwaitingFinancePayment", false), + new ClaimNavigatorItem("Job.Lists.AwaitingTechnicianAction", false), + new ClaimNavigatorItem("Job.Lists.AwaitingUserAction", false), + new ClaimNavigatorItem("Job.Lists.DevicesAwaitingRepair", false), + new ClaimNavigatorItem("Job.Lists.DevicesReadyForReturn", false), + new ClaimNavigatorItem("Job.Lists.JobQueueLists", false), + new ClaimNavigatorItem("Job.Lists.Locations", false), + new ClaimNavigatorItem("Job.Lists.LongRunningJobs", false), + new ClaimNavigatorItem("Job.Lists.MyJobs", false), + new ClaimNavigatorItem("Job.Lists.MyJobsOrphaned", false), + new ClaimNavigatorItem("Job.Lists.RecentlyClosed", false) + }), + new ClaimNavigatorItem("Job.Search", false), + new ClaimNavigatorItem("Job.ShowAttachments", false), + new ClaimNavigatorItem("Job.ShowDailyChart", false), + new ClaimNavigatorItem("Job.ShowFlags", false), + new ClaimNavigatorItem("Job.Show", false), + new ClaimNavigatorItem("Job.ShowJobsQueues", false), + new ClaimNavigatorItem("Job.ShowLogs", false), + new ClaimNavigatorItem("Job.ShowNonWarrantyComponents", false), + new ClaimNavigatorItem("Job.ShowNonWarrantyFinance", false), + new ClaimNavigatorItem("Job.ShowNonWarrantyInsurance", false), + new ClaimNavigatorItem("Job.ShowNonWarrantyRepairs", false), + new ClaimNavigatorItem("Job.ShowWarranty", false), new ClaimNavigatorItem("Job.Types", "Types", "Permissions related to Job Types", false, new List() { new ClaimNavigatorItem("Job.Types.ShowHMisc", false), new ClaimNavigatorItem("Job.Types.ShowHNWar", false), @@ -335,27 +386,9 @@ namespace Disco.Services.Authorization new ClaimNavigatorItem("Job.Types.ShowSOS", false), new ClaimNavigatorItem("Job.Types.ShowSImg", false), new ClaimNavigatorItem("Job.Types.ShowUMgmt", false) - }), - new ClaimNavigatorItem("Job.Search", false), - new ClaimNavigatorItem("Job.ShowAttachments", false), - new ClaimNavigatorItem("Job.ShowDailyChart", false), - new ClaimNavigatorItem("Job.ShowFlags", false), - new ClaimNavigatorItem("Job.Show", false), - new ClaimNavigatorItem("Job.ShowLogs", false), - new ClaimNavigatorItem("Job.ShowNonWarrantyComponents", false), - new ClaimNavigatorItem("Job.ShowNonWarrantyFinance", false), - new ClaimNavigatorItem("Job.ShowNonWarrantyInsurance", false), - new ClaimNavigatorItem("Job.ShowNonWarrantyRepairs", false), - new ClaimNavigatorItem("Job.ShowWarranty", false) + }) }), new ClaimNavigatorItem("Device", "Device", "Permissions related to Devices", false, new List() { - new ClaimNavigatorItem("Device.Properties", "Device Properties", "Permissions related to Device Properties", false, new List() { - new ClaimNavigatorItem("Device.Properties.AssetNumber", false), - new ClaimNavigatorItem("Device.Properties.Details", false), - new ClaimNavigatorItem("Device.Properties.DeviceBatch", false), - new ClaimNavigatorItem("Device.Properties.DeviceProfile", false), - new ClaimNavigatorItem("Device.Properties.Location", false) - }), new ClaimNavigatorItem("Device.Actions", "Actions", "Permissions related to Device Actions", false, new List() { new ClaimNavigatorItem("Device.Actions.AddAttachments", false), new ClaimNavigatorItem("Device.Actions.AllowUnauthenticatedEnrol", false), @@ -370,6 +403,13 @@ namespace Disco.Services.Authorization new ClaimNavigatorItem("Device.Actions.RemoveAnyAttachments", false), new ClaimNavigatorItem("Device.Actions.RemoveOwnAttachments", false) }), + new ClaimNavigatorItem("Device.Properties", "Device Properties", "Permissions related to Device Properties", false, new List() { + new ClaimNavigatorItem("Device.Properties.AssetNumber", false), + new ClaimNavigatorItem("Device.Properties.Details", false), + new ClaimNavigatorItem("Device.Properties.DeviceBatch", false), + new ClaimNavigatorItem("Device.Properties.DeviceProfile", false), + new ClaimNavigatorItem("Device.Properties.Location", false) + }), new ClaimNavigatorItem("Device.Search", false), new ClaimNavigatorItem("Device.ShowAssignmentHistory", false), new ClaimNavigatorItem("Device.ShowAttachments", false), @@ -500,6 +540,10 @@ namespace Disco.Services.Authorization c.Config.Organisation.Show = true; c.Config.JobPreferences.Configure = true; c.Config.JobPreferences.Show = true; + c.Config.JobQueue.Configure = true; + c.Config.JobQueue.Create = true; + c.Config.JobQueue.Delete = true; + c.Config.JobQueue.Show = true; c.Config.Show = true; c.Job.Lists.AllOpen = true; c.Job.Lists.AwaitingFinanceAgreementBreach = true; @@ -511,11 +555,16 @@ namespace Disco.Services.Authorization c.Job.Lists.AwaitingUserAction = true; c.Job.Lists.DevicesAwaitingRepair = true; c.Job.Lists.DevicesReadyForReturn = true; + c.Job.Lists.JobQueueLists = true; c.Job.Lists.Locations = true; c.Job.Lists.LongRunningJobs = true; + c.Job.Lists.MyJobs = true; + c.Job.Lists.MyJobsOrphaned = true; c.Job.Lists.RecentlyClosed = true; c.Job.Actions.AddAttachments = true; c.Job.Actions.AddLogs = true; + c.Job.Actions.AddAnyQueues = true; + c.Job.Actions.AddOwnQueues = true; c.Job.Actions.Close = true; c.Job.Actions.ConvertHWarToHNWar = true; c.Job.Actions.Create = true; @@ -526,6 +575,8 @@ namespace Disco.Services.Authorization c.Job.Actions.LogWarranty = true; c.Job.Actions.RemoveAnyAttachments = true; c.Job.Actions.RemoveAnyLogs = true; + c.Job.Actions.RemoveAnyQueues = true; + c.Job.Actions.RemoveOwnQueues = true; c.Job.Actions.RemoveOwnAttachments = true; c.Job.Actions.RemoveOwnLogs = true; c.Job.Actions.Reopen = true; @@ -552,6 +603,12 @@ namespace Disco.Services.Authorization c.Job.Properties.NonWarrantyProperties.RepairerLoggedDate = true; c.Job.Properties.NonWarrantyProperties.RepairerName = true; c.Job.Properties.NonWarrantyProperties.RepairerReference = true; + c.Job.Properties.JobQueueProperties.EditAnyComments = true; + c.Job.Properties.JobQueueProperties.EditAnyPriority = true; + c.Job.Properties.JobQueueProperties.EditAnySLA = true; + c.Job.Properties.JobQueueProperties.EditOwnComments = true; + c.Job.Properties.JobQueueProperties.EditOwnPriority = true; + c.Job.Properties.JobQueueProperties.EditOwnSLA = true; c.Job.Properties.DeviceHeldLocation = true; c.Job.Properties.DeviceHeld = true; c.Job.Properties.DeviceReadyForReturn = true; @@ -572,6 +629,7 @@ namespace Disco.Services.Authorization c.Job.ShowDailyChart = true; c.Job.ShowFlags = true; c.Job.Show = true; + c.Job.ShowJobsQueues = true; c.Job.ShowLogs = true; c.Job.ShowNonWarrantyComponents = true; c.Job.ShowNonWarrantyFinance = true; @@ -631,7 +689,7 @@ namespace Disco.Services.Authorization public static class Config { - /// Device Certificate + /// Device Certificates /// Permissions related to Device Certificates /// public static class DeviceCertificate @@ -670,7 +728,7 @@ namespace Disco.Services.Authorization public const string ShowStatus = "Config.Enrolment.ShowStatus"; } - /// Device Batch + /// Device Batches /// Permissions related to Device Batches /// public static class DeviceBatch @@ -702,7 +760,7 @@ namespace Disco.Services.Authorization public const string ShowTimeline = "Config.DeviceBatch.ShowTimeline"; } - /// Device Model + /// Device Models /// Permissions related to Device Models /// public static class DeviceModel @@ -729,7 +787,7 @@ namespace Disco.Services.Authorization public const string Show = "Config.DeviceModel.Show"; } - /// Device Profile + /// Device Profiles /// Permissions related to Device Profiles /// public static class DeviceProfile @@ -766,7 +824,7 @@ namespace Disco.Services.Authorization public const string Show = "Config.DeviceProfile.Show"; } - /// Document Template + /// Document Templates /// Permissions related to Document Templates /// public static class DocumentTemplate @@ -928,6 +986,33 @@ namespace Disco.Services.Authorization public const string Show = "Config.JobPreferences.Show"; } + /// Job Queues + /// Permissions related to Job Queues + /// + public static class JobQueue + { + + /// Configure Job Queues + /// Can configure job queues + /// + public const string Configure = "Config.JobQueue.Configure"; + + /// Create Job Queues + /// Can create job queues + /// + public const string Create = "Config.JobQueue.Create"; + + /// Delete Job Queues + /// Can delete job queues + /// + public const string Delete = "Config.JobQueue.Delete"; + + /// Show Job Queues + /// Can show job queues + /// + public const string Show = "Config.JobQueue.Show"; + } + /// Show Configuration /// Can show the configuration menu /// @@ -996,6 +1081,11 @@ namespace Disco.Services.Authorization /// public const string DevicesReadyForReturn = "Job.Lists.DevicesReadyForReturn"; + /// Job Queue Lists + /// Can show job queue lists + /// + public const string JobQueueLists = "Job.Lists.JobQueueLists"; + /// Locations List /// Can show list /// @@ -1006,6 +1096,16 @@ namespace Disco.Services.Authorization /// public const string LongRunningJobs = "Job.Lists.LongRunningJobs"; + /// My Jobs List + /// Can show list + /// + public const string MyJobs = "Job.Lists.MyJobs"; + + /// My Jobs List (Includes No Queue) + /// Can show list + /// + public const string MyJobsOrphaned = "Job.Lists.MyJobsOrphaned"; + /// Recently Closed List /// Can show list /// @@ -1028,6 +1128,16 @@ namespace Disco.Services.Authorization /// public const string AddLogs = "Job.Actions.AddLogs"; + /// Add to Any Queues + /// Can add to any job queues + /// + public const string AddAnyQueues = "Job.Actions.AddAnyQueues"; + + /// Add to Own Queues + /// Can add to own job queues + /// + public const string AddOwnQueues = "Job.Actions.AddOwnQueues"; + /// Close Jobs /// Can close jobs /// @@ -1078,6 +1188,16 @@ namespace Disco.Services.Authorization /// public const string RemoveAnyLogs = "Job.Actions.RemoveAnyLogs"; + /// Remove from Any Queues + /// Can remove from any job queues + /// + public const string RemoveAnyQueues = "Job.Actions.RemoveAnyQueues"; + + /// Remove from Own Queues + /// Can remove from own job queues + /// + public const string RemoveOwnQueues = "Job.Actions.RemoveOwnQueues"; + /// Remove Own Attachments /// Can remove own attachments from jobs /// @@ -1229,6 +1349,43 @@ namespace Disco.Services.Authorization public const string RepairerReference = "Job.Properties.NonWarrantyProperties.RepairerReference"; } + /// Job Queue Properties + /// Permissions related to Job Queue Job Properties + /// + public static class JobQueueProperties + { + + /// Edit Any Comments + /// Can edit any job queue comments + /// + public const string EditAnyComments = "Job.Properties.JobQueueProperties.EditAnyComments"; + + /// Edit Any Priority + /// Can edit any job queue Priority + /// + public const string EditAnyPriority = "Job.Properties.JobQueueProperties.EditAnyPriority"; + + /// Edit Any SLA + /// Can edit any job queue SLA + /// + public const string EditAnySLA = "Job.Properties.JobQueueProperties.EditAnySLA"; + + /// Edit Own Comments + /// Can edit own job queue comments + /// + public const string EditOwnComments = "Job.Properties.JobQueueProperties.EditOwnComments"; + + /// Edit Own Priority + /// Can edit own job queue Priority + /// + public const string EditOwnPriority = "Job.Properties.JobQueueProperties.EditOwnPriority"; + + /// Edit Own SLA + /// Can edit own job queue SLA + /// + public const string EditOwnSLA = "Job.Properties.JobQueueProperties.EditOwnSLA"; + } + /// Device Held Location Property /// Can update property /// @@ -1337,6 +1494,11 @@ namespace Disco.Services.Authorization /// public const string Show = "Job.Show"; + /// Show Jobs Queues + /// Can show jobs queues + /// + public const string ShowJobsQueues = "Job.ShowJobsQueues"; + /// Show Logs /// Can show job logs /// diff --git a/Disco.Services/Authorization/Claims.tt b/Disco.Services/Authorization/Claims.tt index 30a785c8..347c3bc3 100644 --- a/Disco.Services/Authorization/Claims.tt +++ b/Disco.Services/Authorization/Claims.tt @@ -53,7 +53,7 @@ // 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. -using Disco.Models.Authorization; +using Disco.Models.Services.Authorization; using Disco.Models.Repository; using Disco.Services.Authorization.Roles; using System; @@ -213,10 +213,11 @@ void WriteNavigator_Recurse(Permission p, string Prefix){ var groupPrefix = string.Concat(key, "."); WriteLine("new ClaimNavigatorItem(\"{0}{1}\", \"{2}\", \"{3}\", {4}, new List() {{", Prefix, p.Name, p.FriendlyName, p.Description, p.Hidden ? "true" : "false"); PushIndent(" "); - for (int childIndex = 0; childIndex < p.Children.Count; childIndex++) + var children = p.Children.OrderBy(c => c.FriendlyName).ToList(); + for (int childIndex = 0; childIndex < children.Count; childIndex++) { - WriteNavigator_Recurse(p.Children[childIndex], groupPrefix); - if (childIndex < p.Children.Count -1) + WriteNavigator_Recurse(children[childIndex], groupPrefix); + if (childIndex < children.Count -1) WriteLine(","); else WriteLine(string.Empty); diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/ConfigClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/ConfigClaims.cs index 17217244..5d95c2f5 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/ConfigClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/ConfigClaims.cs @@ -5,6 +5,7 @@ using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceProfile using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DocumentTemplate; using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Enrolment; using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.JobPreferences; +using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.JobQueue; using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Logging; using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Origanisation; using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Plugin; @@ -28,6 +29,7 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration this.System = new SystemClaims(); this.Organisation = new OrganisationClaims(); this.JobPreferences = new JobPreferencesClaims(); + this.JobQueue = new JobQueueClaims(); } [ClaimDetails("Show Configuration", "Can show the configuration menu")] @@ -54,5 +56,7 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration public OrganisationClaims Organisation { get; set; } public JobPreferencesClaims JobPreferences { get; set; } + + public JobQueueClaims JobQueue { get; set; } } } diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceBatch/DeviceBatchClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceBatch/DeviceBatchClaims.cs index 927a16d4..85b00cee 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceBatch/DeviceBatchClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceBatch/DeviceBatchClaims.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceBatch { - [ClaimDetails("Device Batch", "Permissions related to Device Batches")] + [ClaimDetails("Device Batches", "Permissions related to Device Batches")] public class DeviceBatchClaims : BaseRoleClaimGroup { [ClaimDetails("Configure Device Batches", "Can configure device batches")] diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceCertificate/DeviceCertificateClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceCertificate/DeviceCertificateClaims.cs index a1c97058..a25a8838 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceCertificate/DeviceCertificateClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceCertificate/DeviceCertificateClaims.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceCertificate { - [ClaimDetails("Device Certificate", "Permissions related to Device Certificates")] + [ClaimDetails("Device Certificates", "Permissions related to Device Certificates")] public class DeviceCertificateClaims : BaseRoleClaimGroup { [ClaimDetails("Download Certificates", "Can download certificates")] diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceModel/DeviceModelClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceModel/DeviceModelClaims.cs index 71f12188..ee6180fc 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceModel/DeviceModelClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceModel/DeviceModelClaims.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceModel { - [ClaimDetails("Device Model", "Permissions related to Device Models")] + [ClaimDetails("Device Models", "Permissions related to Device Models")] public class DeviceModelClaims : BaseRoleClaimGroup { [ClaimDetails("Configure Device Models", "Can configure device models")] diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceProfile/DeviceProfileClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceProfile/DeviceProfileClaims.cs index 709dd2fd..a492d9ed 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceProfile/DeviceProfileClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DeviceProfile/DeviceProfileClaims.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceProfile { - [ClaimDetails("Device Profile", "Permissions related to Device Profiles")] + [ClaimDetails("Device Profiles", "Permissions related to Device Profiles")] public class DeviceProfileClaims : BaseRoleClaimGroup { [ClaimDetails("Configure Device Profiles", "Can configure device profiles")] diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DocumentTemplate/DocumentTemplateClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DocumentTemplate/DocumentTemplateClaims.cs index 0d31d347..adf977a0 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DocumentTemplate/DocumentTemplateClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/DocumentTemplate/DocumentTemplateClaims.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DocumentTemplate { - [ClaimDetails("Document Template", "Permissions related to Document Templates")] + [ClaimDetails("Document Templates", "Permissions related to Document Templates")] public class DocumentTemplateClaims : BaseRoleClaimGroup { [ClaimDetails("Configure Document Templates", "Can configure document templates")] diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/JobQueue/JobQueueClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/JobQueue/JobQueueClaims.cs new file mode 100644 index 00000000..34f32731 --- /dev/null +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Configuration/JobQueue/JobQueueClaims.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.JobQueue +{ + [ClaimDetails("Job Queues", "Permissions related to Job Queues")] + public class JobQueueClaims : BaseRoleClaimGroup + { + [ClaimDetails("Configure Job Queues", "Can configure job queues")] + public bool Configure { get; set; } + + [ClaimDetails("Create Job Queues", "Can create job queues")] + public bool Create { get; set; } + + [ClaimDetails("Delete Job Queues", "Can delete job queues")] + public bool Delete { get; set; } + + [ClaimDetails("Show Job Queues", "Can show job queues")] + public bool Show { get; set; } + } +} diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobActionsClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobActionsClaims.cs index 779df4dd..a0a4195c 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobActionsClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobActionsClaims.cs @@ -20,6 +20,15 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Job [ClaimDetails("Delete Jobs", "Can delete jobs")] public bool Delete { get; set; } + [ClaimDetails("Add to Own Queues", "Can add to own job queues")] + public bool AddOwnQueues { get; set; } + [ClaimDetails("Add to Any Queues", "Can add to any job queues")] + public bool AddAnyQueues { get; set; } + [ClaimDetails("Remove from Own Queues", "Can remove from own job queues")] + public bool RemoveOwnQueues { get; set; } + [ClaimDetails("Remove from Any Queues", "Can remove from any job queues")] + public bool RemoveAnyQueues { get; set; } + [ClaimDetails("Log Warranty", "Can log warranty for jobs")] public bool LogWarranty { get; set; } [ClaimDetails("Log Repair", "Can log repair for non-warranty jobs")] diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobClaims.cs index 78ba49f4..808979ce 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobClaims.cs @@ -31,6 +31,9 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Job [ClaimDetails("Show Attachments", "Can show job attachments")] public bool ShowAttachments { get; set; } + [ClaimDetails("Show Jobs Queues", "Can show jobs queues")] + public bool ShowJobsQueues { get; set; } + [ClaimDetails("Show Non-Warranty Components", "Can show non-warranty job components")] public bool ShowNonWarrantyComponents { get; set; } [ClaimDetails("Show Non-Warranty Finance", "Can show non-warranty job finance")] diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobListsClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobListsClaims.cs index f89336e5..d2b9baee 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobListsClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobListsClaims.cs @@ -9,6 +9,14 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Job [ClaimDetails("Lists", "Permissions related to Job Lists")] public class JobListsClaims : BaseRoleClaimGroup { + [ClaimDetails("Job Queue Lists", "Can show job queue lists")] + public bool JobQueueLists { get; set; } + + [ClaimDetails("My Jobs List", "Can show list")] + public bool MyJobs { get; set; } + [ClaimDetails("My Jobs List (Includes No Queue)", "Can show list")] + public bool MyJobsOrphaned { get; set; } + [ClaimDetails("Awaiting Technician Action List", "Can show list")] public bool AwaitingTechnicianAction { get; set; } [ClaimDetails("Long Running Jobs List", "Can show list")] diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobPropertiesClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobPropertiesClaims.cs index de2ecd5c..780551b0 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobPropertiesClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobPropertiesClaims.cs @@ -13,10 +13,12 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Job { this.WarrantyProperties = new JobWarrantyPropertiesClaims(); this.NonWarrantyProperties = new JobNonWarrantyPropertiesClaims(); + this.JobQueueProperties = new JobQueuePropertiesClaims(); } public JobWarrantyPropertiesClaims WarrantyProperties { get; set; } public JobNonWarrantyPropertiesClaims NonWarrantyProperties { get; set; } + public JobQueuePropertiesClaims JobQueueProperties { get; set; } [ClaimDetails("Device Held Property", "Can update property")] public bool DeviceHeld { get; set; } diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobQueuePropertiesClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobQueuePropertiesClaims.cs new file mode 100644 index 00000000..f9eb2a4e --- /dev/null +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobQueuePropertiesClaims.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Services.Authorization.Roles.ClaimGroups.Job +{ + [ClaimDetails("Job Queue Properties", "Permissions related to Job Queue Job Properties")] + public class JobQueuePropertiesClaims : BaseRoleClaimGroup + { + [ClaimDetails("Edit Any Comments", "Can edit any job queue comments")] + public bool EditAnyComments { get; set; } + [ClaimDetails("Edit Own Comments", "Can edit own job queue comments")] + public bool EditOwnComments { get; set; } + + [ClaimDetails("Edit Any SLA", "Can edit any job queue SLA")] + public bool EditAnySLA { get; set; } + [ClaimDetails("Edit Own SLA", "Can edit own job queue SLA")] + public bool EditOwnSLA { get; set; } + + [ClaimDetails("Edit Any Priority", "Can edit any job queue Priority")] + public bool EditAnyPriority { get; set; } + [ClaimDetails("Edit Own Priority", "Can edit own job queue Priority")] + public bool EditOwnPriority { get; set; } + } +} diff --git a/Disco.Services/Authorization/Roles/RoleCache.cs b/Disco.Services/Authorization/Roles/RoleCache.cs index 6ffb47f8..c8df3160 100644 --- a/Disco.Services/Authorization/Roles/RoleCache.cs +++ b/Disco.Services/Authorization/Roles/RoleCache.cs @@ -1,5 +1,5 @@ using Disco.Data.Repository; -using Disco.Models.Authorization; +using Disco.Models.Services.Authorization; using Disco.Models.Repository; using System; using System.Collections.Concurrent; diff --git a/Disco.Services/Authorization/Roles/RoleToken.cs b/Disco.Services/Authorization/Roles/RoleToken.cs index 0c78e10b..dd19894f 100644 --- a/Disco.Services/Authorization/Roles/RoleToken.cs +++ b/Disco.Services/Authorization/Roles/RoleToken.cs @@ -1,4 +1,4 @@ -using Disco.Models.Authorization; +using Disco.Models.Services.Authorization; using Disco.Models.Repository; using Newtonsoft.Json; using System; diff --git a/Disco.Services/Disco.Services.csproj b/Disco.Services/Disco.Services.csproj index 848e0ebe..86ccf60e 100644 --- a/Disco.Services/Disco.Services.csproj +++ b/Disco.Services/Disco.Services.csproj @@ -75,6 +75,21 @@ + + False + ..\packages\Rx-Core.2.1.30214.0\lib\Net45\System.Reactive.Core.dll + + + False + ..\packages\Rx-Interfaces.2.1.30214.0\lib\Net45\System.Reactive.Interfaces.dll + + + False + ..\packages\Rx-Linq.2.1.30214.0\lib\Net45\System.Reactive.Linq.dll + + + ..\packages\Rx-PlatformServices.2.1.30214.0\lib\Net45\System.Reactive.PlatformServices.dll + @@ -130,6 +145,7 @@ + @@ -142,6 +158,7 @@ + @@ -156,6 +173,13 @@ + + + + + + + diff --git a/Disco.Services/Jobs/JobExtensions.cs b/Disco.Services/Jobs/JobExtensions.cs new file mode 100644 index 00000000..245265dc --- /dev/null +++ b/Disco.Services/Jobs/JobExtensions.cs @@ -0,0 +1,195 @@ +using Disco.Models.Repository; +using Disco.Models.Services.Jobs.JobLists; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Services +{ + public static class JobExtensions + { + public static JobTableStatusItemModel ToJobTableStatusItemModel(this Job j) + { + var i = new JobTableStatusItemModel() + { + Id = j.Id, + OpenedDate = j.OpenedDate, + ClosedDate = j.ClosedDate, + JobTypeId = j.JobTypeId, + JobTypeDescription = j.JobType.Description, + DeviceHeldLocation = j.DeviceHeldLocation, + Flags = j.Flags, + + WaitingForUserAction = j.WaitingForUserAction, + DeviceReadyForReturn = j.DeviceReadyForReturn, + DeviceHeld = j.DeviceHeld, + DeviceReturnedDate = j.DeviceReturnedDate + }; + + if (j.Device != null) + { + i.DeviceSerialNumber = j.DeviceSerialNumber; + i.DeviceModelDescription = j.Device.DeviceModel.Description; + i.DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress; + + if (j.JobMetaWarranty != null) + { + i.JobMetaWarranty_ExternalReference = j.JobMetaWarranty.ExternalReference; + i.JobMetaWarranty_ExternalLoggedDate = j.JobMetaWarranty.ExternalLoggedDate; + i.JobMetaWarranty_ExternalCompletedDate = j.JobMetaWarranty.ExternalCompletedDate; + i.JobMetaWarranty_ExternalName = j.JobMetaWarranty.ExternalName; + } + if (j.JobMetaNonWarranty != null) + { + i.JobMetaNonWarranty_RepairerLoggedDate = j.JobMetaNonWarranty.RepairerLoggedDate; + i.JobMetaNonWarranty_RepairerCompletedDate = j.JobMetaNonWarranty.RepairerCompletedDate; + i.JobMetaNonWarranty_AccountingChargeAddedDate = j.JobMetaNonWarranty.AccountingChargeAddedDate; + i.JobMetaNonWarranty_AccountingChargePaidDate = j.JobMetaNonWarranty.AccountingChargePaidDate; + i.JobMetaNonWarranty_AccountingChargeRequiredDate = j.JobMetaNonWarranty.AccountingChargeRequiredDate; + i.JobMetaNonWarranty_IsInsuranceClaim = j.JobMetaNonWarranty.IsInsuranceClaim; + i.JobMetaNonWarranty_RepairerName = j.JobMetaNonWarranty.RepairerName; + if (j.JobMetaInsurance != null) + { + i.JobMetaInsurance_ClaimFormSentDate = j.JobMetaInsurance.ClaimFormSentDate; + } + } + + } + if (j.User != null) + { + i.UserId = j.UserId; + i.UserDisplayName = j.User.DisplayName; + } + if (j.OpenedTechUser != null) + { + i.OpenedTechUserId = j.OpenedTechUserId; + i.OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName; + } + + return i; + } + + public static string JobStatusDescription(string StatusId, Job j = null) + { + switch (StatusId) + { + case Job.JobStatusIds.Open: + return "Open"; + case Job.JobStatusIds.Closed: + return "Closed"; + case Job.JobStatusIds.AwaitingWarrantyRepair: + if (j == null) + return "Awaiting Warranty Repair"; + else + if (j.DeviceHeld.HasValue) + return string.Format("Awaiting Warranty Repair ({0})", j.JobMetaWarranty.ExternalName); + else + return string.Format("Awaiting Warranty Repair - Not Held ({0})", j.JobMetaWarranty.ExternalName); + case Job.JobStatusIds.AwaitingRepairs: + if (j == null) + return "Awaiting Repairs"; + else + if (j.DeviceHeld.HasValue) + return string.Format("Awaiting Repairs ({0})", j.JobMetaNonWarranty.RepairerName); + else + return string.Format("Awaiting Repairs - Not Held ({0})", j.JobMetaNonWarranty.RepairerName); + case Job.JobStatusIds.AwaitingDeviceReturn: + return "Awaiting Device Return"; + case Job.JobStatusIds.AwaitingUserAction: + return "Awaiting User Action"; + case Job.JobStatusIds.AwaitingAccountingPayment: + return "Awaiting Accounting Payment"; + case Job.JobStatusIds.AwaitingAccountingCharge: + return "Awaiting Accounting Charge"; + case Job.JobStatusIds.AwaitingInsuranceProcessing: + return "Awaiting Insurance Processing"; + default: + return "Unknown"; + } + } + + public static string JobStatusDescription(string StatusId, JobTableStatusItemModel j = null) + { + switch (StatusId) + { + case Job.JobStatusIds.Open: + return "Open"; + case Job.JobStatusIds.Closed: + return "Closed"; + case Job.JobStatusIds.AwaitingWarrantyRepair: + if (j == null) + return "Awaiting Warranty Repair"; + else + if (j.DeviceHeld.HasValue) + return string.Format("Awaiting Warranty Repair ({0})", j.JobMetaWarranty_ExternalName); + else + return string.Format("Awaiting Warranty Repair - Not Held ({0})", j.JobMetaWarranty_ExternalName); + case Job.JobStatusIds.AwaitingRepairs: + if (j == null) + return "Awaiting Repairs"; + else + if (j.DeviceHeld.HasValue) + return string.Format("Awaiting Repairs ({0})", j.JobMetaNonWarranty_RepairerName); + else + return string.Format("Awaiting Repairs - Not Held ({0})", j.JobMetaNonWarranty_RepairerName); + case Job.JobStatusIds.AwaitingDeviceReturn: + return "Awaiting Device Return"; + case Job.JobStatusIds.AwaitingUserAction: + return "Awaiting User Action"; + case Job.JobStatusIds.AwaitingAccountingPayment: + return "Awaiting Accounting Payment"; + case Job.JobStatusIds.AwaitingAccountingCharge: + return "Awaiting Accounting Charge"; + case Job.JobStatusIds.AwaitingInsuranceProcessing: + return "Awaiting Insurance Processing"; + default: + return "Unknown"; + } + } + + public static string CalculateStatusId(this Job j) + { + return j.ToJobTableStatusItemModel().CalculateStatusId(); + } + + public static string CalculateStatusId(this JobTableStatusItemModel j) + { + if (j.ClosedDate.HasValue) + return Job.JobStatusIds.Closed; + + if (j.JobTypeId == JobType.JobTypeIds.HWar) + { + if (!string.IsNullOrEmpty(j.JobMetaWarranty_ExternalReference) && !j.JobMetaWarranty_ExternalCompletedDate.HasValue) + return Job.JobStatusIds.AwaitingWarrantyRepair; // Job Logged - but not marked as completed + } + + if (j.JobTypeId == JobType.JobTypeIds.HNWar) + { + if (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty_RepairerCompletedDate.HasValue) + return Job.JobStatusIds.AwaitingRepairs; // Repairs logged - but not complete + if (j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue) + return Job.JobStatusIds.AwaitingAccountingPayment; // Accounting Charge Added, but not paid + if (j.JobMetaNonWarranty_AccountingChargeRequiredDate.HasValue && (!j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue || !j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue)) + return Job.JobStatusIds.AwaitingAccountingCharge; // Accounting Charge Required, but not added or paid + if (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && j.JobMetaNonWarranty_IsInsuranceClaim.Value && !j.JobMetaInsurance_ClaimFormSentDate.HasValue) + return Job.JobStatusIds.AwaitingInsuranceProcessing; // Is insurance claim, but no Claim Form Sent + } + + if (j.WaitingForUserAction.HasValue) + return Job.JobStatusIds.AwaitingUserAction; // Awaiting for User + + if (j.DeviceReadyForReturn.HasValue && !j.DeviceReturnedDate.HasValue) + return Job.JobStatusIds.AwaitingDeviceReturn; // Device not returned to User + + return Job.JobStatusIds.Open; + } + + public static Tuple Status(this Job j) + { + var statusId = j.CalculateStatusId(); + return new Tuple(statusId, JobStatusDescription(statusId, j)); + } + } +} diff --git a/Disco.BI/BI/Extensions/JobTableExtensions.cs b/Disco.Services/Jobs/JobLists/JobTableExtensions.cs similarity index 63% rename from Disco.BI/BI/Extensions/JobTableExtensions.cs rename to Disco.Services/Jobs/JobLists/JobTableExtensions.cs index 381daa56..488aac01 100644 --- a/Disco.BI/BI/Extensions/JobTableExtensions.cs +++ b/Disco.Services/Jobs/JobLists/JobTableExtensions.cs @@ -1,17 +1,59 @@ -using System; +using Disco.Data.Repository; +using Disco.Models.Repository; +using Disco.Models.Services.Jobs.JobLists; +using Disco.Services.Authorization; +using Disco.Services.Users; +using System; using System.Collections.Generic; using System.Linq; using System.Text; -using Disco.Models.BI.Job; -using Disco.Models.Repository; -using Disco.Data.Repository; -using Disco.Services.Users; -using Disco.Services.Authorization; +using System.Threading.Tasks; -namespace Disco.BI.Extensions +namespace Disco.Services { public static class JobTableExtensions { + private static JobTableModel CloneEmptyJobTableModel(JobTableModel Model) + { + return new JobTableModel() + { + ShowId = Model.ShowId, + ShowDeviceAddress = Model.ShowDeviceAddress, + ShowDates = Model.ShowDates, + ShowType = Model.ShowType, + ShowDevice = Model.ShowDevice, + ShowUser = Model.ShowUser, + ShowTechnician = Model.ShowTechnician, + ShowLocation = Model.ShowLocation, + ShowStatus = Model.ShowStatus, + IsSmallTable = Model.IsSmallTable, + HideClosedJobs = Model.HideClosedJobs, + EnablePaging = Model.EnablePaging, + EnableFilter = Model.EnableFilter + }; + } + + public static IDictionary MultiCampusModels(this JobTableModel Model) + { + var items = Model.Items; + if (items == null || items.Count() > 0) + { + return items.OrderBy(i => i.DeviceAddress).GroupBy(i => i.DeviceAddress).ToDictionary( + ig => ig.Key ?? string.Empty, + ig => + { + var jtm = CloneEmptyJobTableModel(Model); + jtm.Items = ig.ToList(); + return jtm; + } + ); + } + else + { + return null; + } + } + private static List FilterAllowedTypes(AuthorizationToken Authorization) { if (!Authorization.HasAll(Claims.Job.Types.ShowHMisc, Claims.Job.Types.ShowHNWar, Claims.Job.Types.ShowHWar, Claims.Job.Types.ShowSApp, Claims.Job.Types.ShowSImg, Claims.Job.Types.ShowSOS, Claims.Job.Types.ShowUMgmt)) @@ -50,24 +92,24 @@ namespace Disco.BI.Extensions return Jobs; } - public static List PermissionsFiltered(this List Items, AuthorizationToken Authorization) + public static IEnumerable PermissionsFiltered(this IEnumerable Items, AuthorizationToken Authorization) { - if (Items != null && Items.Count > 0) + if (Items != null && Items.Count() > 0) { var allowedTypes = FilterAllowedTypes(Authorization); if (allowedTypes != null) { - return Items.Where(j => allowedTypes.Contains(j.TypeId)).ToList(); + return Items.Where(j => allowedTypes.Contains(j.JobTypeId)).ToList(); } } return Items; } - public static List DetermineItems(this JobTableModel model, DiscoDataContext Database, IQueryable Jobs) + public static IEnumerable DetermineItems(this JobTableModel model, DiscoDataContext Database, IQueryable Jobs) { - List items; + List items; // Permissions var auth = UserService.CurrentAuthorization; @@ -96,13 +138,13 @@ namespace Disco.BI.Extensions if (model.ShowStatus) { - var jobItems = Jobs.Select(j => new JobTableModel.JobTableItemModelIncludeStatus() + var jobItems = Jobs.Select(j => new JobTableStatusItemModel() { Id = j.Id, OpenedDate = j.OpenedDate, ClosedDate = j.ClosedDate, - TypeId = j.JobTypeId, - TypeDescription = j.JobType.Description, + JobTypeId = j.JobTypeId, + JobTypeDescription = j.JobType.Description, DeviceSerialNumber = j.Device.SerialNumber, DeviceProfileId = j.Device.DeviceProfileId, DeviceModelId = j.Device.DeviceModelId, @@ -112,9 +154,11 @@ namespace Disco.BI.Extensions UserDisplayName = j.User.DisplayName, OpenedTechUserId = j.OpenedTechUserId, OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName, - Location = j.DeviceHeldLocation, + DeviceHeldLocation = j.DeviceHeldLocation, + Flags = j.Flags, JobMetaWarranty_ExternalReference = j.JobMetaWarranty.ExternalReference, + JobMetaWarranty_ExternalLoggedDate = j.JobMetaWarranty.ExternalLoggedDate, JobMetaWarranty_ExternalCompletedDate = j.JobMetaWarranty.ExternalCompletedDate, JobMetaNonWarranty_RepairerLoggedDate = j.JobMetaNonWarranty.RepairerLoggedDate, JobMetaNonWarranty_RepairerCompletedDate = j.JobMetaNonWarranty.RepairerCompletedDate, @@ -129,27 +173,35 @@ namespace Disco.BI.Extensions DeviceHeld = j.DeviceHeld, DeviceReturnedDate = j.DeviceReturnedDate, JobMetaWarranty_ExternalName = j.JobMetaWarranty.ExternalName, - JobMetaNonWarranty_RepairerName = j.JobMetaNonWarranty.RepairerName + JobMetaNonWarranty_RepairerName = j.JobMetaNonWarranty.RepairerName, + ActiveJobQueues = j.JobQueues.Where(jq => !jq.RemovedDate.HasValue).Select(jq => new JobTableStatusQueueItemModel() + { + Id = jq.Id, + QueueId = jq.JobQueueId, + AddedDate = jq.AddedDate, + SLAExpiresDate = jq.SLAExpiresDate, + Priority = jq.Priority + }) }); - items = new List(); + items = new List(); foreach (var j in jobItems) { j.StatusId = j.CalculateStatusId(); - j.StatusDescription = JobBI.Utilities.JobStatusDescription(j.StatusId, j); + j.StatusDescription = JobExtensions.JobStatusDescription(j.StatusId, j); items.Add(j); } } else { - items = Jobs.Select(j => new JobTableModel.JobTableItemModel() + items = Jobs.Select(j => new JobTableItemModel() { Id = j.Id, OpenedDate = j.OpenedDate, ClosedDate = j.ClosedDate, - TypeId = j.JobTypeId, - TypeDescription = j.JobType.Description, + JobTypeId = j.JobTypeId, + JobTypeDescription = j.JobType.Description, DeviceSerialNumber = j.Device.SerialNumber, DeviceProfileId = j.Device.DeviceProfileId, DeviceModelId = j.Device.DeviceModelId, @@ -159,7 +211,8 @@ namespace Disco.BI.Extensions UserDisplayName = j.User.DisplayName, OpenedTechUserId = j.OpenedTechUserId, OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName, - Location = j.DeviceHeldLocation + DeviceHeldLocation = j.DeviceHeldLocation, + Flags = j.Flags }).ToList(); } @@ -177,5 +230,21 @@ namespace Disco.BI.Extensions { model.Items = model.DetermineItems(Database, Jobs); } + + public static double? SlaPrecentageRemaining(this IEnumerable queueItems) + { + return queueItems.Where(i => i.SLAExpiresDate.HasValue).Min(i => + { + var total = (i.SLAExpiresDate.Value - i.AddedDate).Ticks; + var remaining = (i.SLAExpiresDate.Value - DateTime.Now).Ticks; + return ((double)remaining / total); + }); + } + + public static IEnumerable UsersQueueItems(this IEnumerable queueItems, AuthorizationToken Authorization) + { + var usersQueues = Jobs.JobQueues.JobQueueService.UsersQueues(Authorization).ToDictionary(q => q.JobQueue.Id); + return queueItems.Where(qi => usersQueues.ContainsKey(qi.QueueId)); + } } } diff --git a/Disco.Services/Jobs/JobLists/ManagedJobList.cs b/Disco.Services/Jobs/JobLists/ManagedJobList.cs new file mode 100644 index 00000000..8efc05ec --- /dev/null +++ b/Disco.Services/Jobs/JobLists/ManagedJobList.cs @@ -0,0 +1,265 @@ +using Disco.Data.Repository; +using Disco.Data.Repository.Monitor; +using Disco.Models.Repository; +using Disco.Models.Services.Jobs.JobLists; +using Disco.Services.Logging; +using Disco.Services.Users; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; + +namespace Disco.Services.Jobs.JobLists +{ + using FilterFunc = Func, IQueryable>; + using SortFunc = Func, IEnumerable>; + using OpenFilterFunc = Func, IEnumerable>; +using Disco.Services.Authorization; + using Disco.Services.Jobs.JobQueues; + + public class ManagedJobList : JobTableModel, IDisposable + { + private static ManagedJobList openJobs; + + private IDisposable unsubscribeToken; + private object updateLock = new object(); + + public string Name { get; private set; } + public FilterFunc FilterFunction { get; private set; } + public SortFunc SortFunction { get; private set; } + + public static OpenFilterFunc AwaitingTechnicianActionFilter = q => q.Where(j => j.ClosedDate == null && !j.WaitingForUserAction.HasValue + && !(j.JobTypeId == JobType.JobTypeIds.HNWar && (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && j.JobMetaNonWarranty_IsInsuranceClaim.Value && !j.JobMetaInsurance_ClaimFormSentDate.HasValue)) + && !(j.JobTypeId == JobType.JobTypeIds.HNWar && (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty_RepairerCompletedDate.HasValue)) + && !(j.JobTypeId == JobType.JobTypeIds.HNWar && (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue)) + && !(j.JobTypeId == JobType.JobTypeIds.HWar && (j.JobMetaWarranty_ExternalLoggedDate.HasValue && !j.JobMetaWarranty_ExternalCompletedDate.HasValue)) + && (j.DeviceHeld == null || j.DeviceReturnedDate != null || j.DeviceReadyForReturn == null)); + + static ManagedJobList() + { + using (var Database = new DiscoDataContext()) + { + openJobs = new ManagedJobList( + Name: "Open Jobs", + FilterFunction: q => q.Where(j => !j.ClosedDate.HasValue), + SortFunction: q => q) + { + ShowDeviceAddress = true, + ShowLocation = true, + ShowStatus = true + }.Initialize(Database); + } + } + + public static JobTableModel OpenJobsTable(OpenFilterFunc FilterFunction) + { + return new JobTableModel() + { + ShowStatus = true, + Items = FilterFunction(openJobs.Items.Cast()) + }; + } + + public static JobTableModel MyJobsTable(AuthorizationToken AuthToken) + { + IEnumerable> allJobs = null; + + if (AuthToken.Has(Claims.Job.Lists.MyJobsOrphaned)) + { + allJobs = AwaitingTechnicianActionFilter( + openJobs.Items.Cast() + .Where(i => i.ActiveJobQueues == null || i.ActiveJobQueues.Count() == 0) + ).Select(i => new Tuple(i, (byte)JobQueuePriority.Normal, (byte)JobQueuePriority.Normal, null)); + } + + var usersQueues = JobQueueService.UsersQueues(AuthToken).ToDictionary(q => q.JobQueue.Id); + + var queueJobs = openJobs.Items.Cast() + .Where(i => i.ActiveJobQueues != null && i.ActiveJobQueues.Any(jqj => usersQueues.ContainsKey(jqj.QueueId))) + .Select(i => new Tuple( + i, + (byte)i.ActiveJobQueues.Where(q => usersQueues.ContainsKey(q.QueueId)).Max(q => (int)usersQueues[q.QueueId].JobQueue.Priority), + (byte)i.ActiveJobQueues.Where(q => usersQueues.ContainsKey(q.QueueId)).Max(q => (int)q.Priority), + i.ActiveJobQueues.Where(q => usersQueues.ContainsKey(q.QueueId) && q.SLAExpiresDate.HasValue).Min(q => q.SLAExpiresDate) + )); + + if (allJobs != null) + allJobs = allJobs.Concat(queueJobs).ToList(); + else + allJobs = queueJobs.ToList(); + + var allJobsSorted = allJobs + .OrderByDescending(i => i.Item2).ThenByDescending(i => i.Item3).ThenBy(i => i.Item4).ThenBy(i => i.Item1.OpenedDate).Select(q => q.Item1); + + return new JobTableModel() + { + ShowStatus = true, + Items = allJobsSorted.ToList() + }; + } + + public override IEnumerable Items + { + get + { + return base.Items.PermissionsFiltered(UserService.CurrentAuthorization); + } + set + { + throw new InvalidOperationException("Items cannot be manually set in a Managed Job List"); + } + } + + public ManagedJobList(string Name, FilterFunc FilterFunction, SortFunc SortFunction) + { + this.Name = Name; + this.FilterFunction = FilterFunction; + this.SortFunction = SortFunction; + } + + public ManagedJobList Initialize(DiscoDataContext Database) + { + // Can only Initialize once + if (base.Items != null) + return ReInitialize(Database); + + lock (updateLock) + { + // Subscribe for Changes + // - Job (or Job Meta) Changes + // - Device Profile Address Changes (for multi-campus Schools) + // - Device Model Description Changes + // - Device's Profile or Model Changes + unsubscribeToken = RepositoryMonitor.StreamAfterCommit + .Where(n => n.EntityType == typeof(Job) || + n.EntityType == typeof(JobQueueJob) || + n.EntityType == typeof(JobMetaWarranty) || + n.EntityType == typeof(JobMetaNonWarranty) || + n.EntityType == typeof(JobMetaInsurance) || + (n.EventType == RepositoryMonitorEventType.Modified && ( + (n.EntityType == typeof(DeviceProfile) && n.ModifiedProperties.Contains("DefaultOrganisationAddress")) || + (n.EntityType == typeof(DeviceModel) && n.ModifiedProperties.Contains("Description")) || + (n.EntityType == typeof(Device) && n.ModifiedProperties.Contains("DeviceProfileId") || n.ModifiedProperties.Contains("DeviceModelId")) + ))) + .Subscribe(JobNotification, NotificationError); + + // Initially fill table + base.Items = this.SortFunction(this.DetermineItems(Database, this.FilterFunction(Database.Jobs))).ToList(); + } + return this; + } + + public ManagedJobList ReInitialize(DiscoDataContext Database) + { + return ReInitialize(Database, null, null); + } + public ManagedJobList ReInitialize(DiscoDataContext Database, FilterFunc FilterFunction) + { + return ReInitialize(Database, FilterFunction, null); + } + public ManagedJobList ReInitialize(DiscoDataContext Database, FilterFunc FilterFunction, SortFunc SortFunction) + { + if (Database == null) + throw new ArgumentNullException("Database"); + + lock (updateLock) + { + if (FilterFunction != null) + this.FilterFunction = FilterFunction; + if (SortFunction != null) + this.SortFunction = SortFunction; + + base.Items = this.SortFunction(this.DetermineItems(Database, this.FilterFunction(Database.Jobs))).ToList(); + } + return this; + } + + private void NotificationError(Exception ex) + { + SystemLog.LogException(string.Format("Disco.Services.Jobs.JobLists.ManagedJobList: [{0}]", this.Name), ex); + } + + private void JobNotification(RepositoryMonitorEvent e) + { + List jobIds = null; + JobTableItemModel[] existingItems = null; + + if (e.EntityType == typeof(Job)) + jobIds = new List() { ((Job)e.Entity).Id }; + else if (e.EntityType == typeof(JobQueueJob)) + jobIds = new List() { ((JobQueueJob)e.Entity).JobId }; + else if (e.EntityType == typeof(JobMetaWarranty)) + jobIds = new List() { ((JobMetaWarranty)e.Entity).JobId }; + else if (e.EntityType == typeof(JobMetaNonWarranty)) + jobIds = new List() { ((JobMetaNonWarranty)e.Entity).JobId }; + else if (e.EntityType == typeof(JobMetaInsurance)) + jobIds = new List() { ((JobMetaInsurance)e.Entity).JobId }; + else if (e.EntityType == typeof(DeviceProfile)) + { + int deviceProfileId = ((DeviceProfile)e.Entity).Id; + existingItems = base.Items.Where(i => i.DeviceProfileId == deviceProfileId).ToArray(); + } + else if (e.EntityType == typeof(DeviceModel)) + { + int deviceModelId = ((DeviceModel)e.Entity).Id; + existingItems = base.Items.Where(i => i.DeviceModelId == deviceModelId).ToArray(); + } + else if (e.EntityType == typeof(Device)) + { + string deviceSerialNumber = ((Device)e.Entity).SerialNumber; + existingItems = base.Items.Where(i => i.DeviceSerialNumber == deviceSerialNumber).ToArray(); + } + else + return; // Subscription should never reach + + if (jobIds == null) + { + if (existingItems == null) + throw new InvalidOperationException("Notification algorithm didn't indicate any Jobs for update"); + else + jobIds = existingItems.Select(i => i.Id).ToList(); + } + + if (jobIds.Count == 0) + return; + else + UpdateJobs(e.Database, jobIds, existingItems); + } + + private void UpdateJobs(DiscoDataContext Database, List jobIds, JobTableItemModel[] existingItems = null) + { + lock (updateLock) + { + // Check for existing items, if not handed them + if (existingItems == null) + existingItems = base.Items.Where(i => jobIds.Contains(i.Id)).ToArray(); + + var updatedItems = this.DetermineItems(Database, this.FilterFunction(Database.Jobs.Where(j => jobIds.Contains(j.Id)))); + + var refreshedList = base.Items.ToList(); + + // Remove Existing + if (existingItems.Length > 0) + foreach (var existingItem in existingItems) + refreshedList.Remove(existingItem); + + // Add Updated Items + if (updatedItems.Count() > 0) + foreach (var updatedItem in updatedItems) + refreshedList.Add(updatedItem); + + // Reorder + base.Items = this.SortFunction(refreshedList).ToList(); + } + } + + public void Dispose() + { + if (unsubscribeToken != null) + { + unsubscribeToken.Dispose(); + unsubscribeToken = null; + } + } + } +} diff --git a/Disco.Services/Jobs/JobQueues/Cache.cs b/Disco.Services/Jobs/JobQueues/Cache.cs new file mode 100644 index 00000000..4675ce81 --- /dev/null +++ b/Disco.Services/Jobs/JobQueues/Cache.cs @@ -0,0 +1,313 @@ +using Disco.Data.Repository; +using Disco.Models.Repository; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Services.Jobs.JobQueues +{ + internal class Cache + { + private ConcurrentDictionary _Cache; + private Dictionary> _SubjectCache; + + private ReadOnlyCollection> _Icons; + private ReadOnlyCollection> _IconColourCache; + private ReadOnlyCollection> _SlaOptions; + + public Cache(DiscoDataContext Database) + { + Initialize(Database); + } + + private void Initialize(DiscoDataContext Database) + { + // Queues from Database + var queues = Database.JobQueues.ToList(); + + // Default System Queue + //var defaultQueue = new JobQueue() + //{ + // Id = 0, + // Name = "Default Queue", + // Description = "Default system queue for orphaned jobs", + // Icon = "question-circle", + // IconColour = "F0A30A", + // DefaultSLAExpiry = null, + // Priority = JobQueuePriority.Normal, + // SubjectIds = null + //}; + //queues.Add(defaultQueue); + + // Add Queues to In-Memory Cache + this._Cache = new ConcurrentDictionary(queues.Select(q => new KeyValuePair(q.Id, JobQueueToken.FromJobQueue(q)))); + + // Calculate Queue Subject Cache + CalculateSubjectCache(); + + #region Predefined Options + // Icons + if (this._Icons == null) + { + this._Icons = new List>(){ + new KeyValuePair("ambulance" , "Ambulance"), + new KeyValuePair("anchor" , "Anchor"), + new KeyValuePair("android" , "Android"), + new KeyValuePair("apple" , "Apple"), + new KeyValuePair("archive" , "Archive"), + new KeyValuePair("arrow-circle-down" , "Arrow Circle Down"), + new KeyValuePair("arrow-circle-left" , "Arrow Circle Left"), + new KeyValuePair("arrow-circle-right" , "Arrow Circle Right"), + new KeyValuePair("arrow-circle-up" , "Arrow Circle Up"), + new KeyValuePair("asterisk" , "Asterisk"), + new KeyValuePair("ban" , "Ban"), + new KeyValuePair("beer" , "Beer"), + new KeyValuePair("bell" , "Bell"), + new KeyValuePair("bolt" , "Bolt"), + new KeyValuePair("book" , "Book"), + new KeyValuePair("bookmark" , "Bookmark"), + new KeyValuePair("briefcase" , "Briefcase"), + new KeyValuePair("bug" , "Bug"), + new KeyValuePair("building-o" , "Building"), + new KeyValuePair("bullhorn" , "Bullhorn"), + new KeyValuePair("bullseye" , "Bullseye"), + new KeyValuePair("calendar" , "Calendar"), + new KeyValuePair("calendar-o" , "Calendar"), + new KeyValuePair("check-circle" , "Check Circle"), + new KeyValuePair("clock-o" , "Clock"), + new KeyValuePair("cloud" , "Cloud"), + new KeyValuePair("coffee" , "Coffee"), + new KeyValuePair("comments" , "Comments"), + new KeyValuePair("compass" , "Compass"), + new KeyValuePair("credit-card" , "Credit Card"), + new KeyValuePair("crosshairs" , "Crosshairs"), + new KeyValuePair("desktop" , "Desktop"), + new KeyValuePair("dollar" , "Dollar"), + new KeyValuePair("dot-circle-o" , "Dot Circle"), + new KeyValuePair("envelope" , "Envelope"), + new KeyValuePair("exclamation" , "Exclamation"), + new KeyValuePair("eye" , "Eye"), + new KeyValuePair("female" , "Female"), + new KeyValuePair("fighter-jet" , "Fighter Jet"), + new KeyValuePair("film" , "Film"), + new KeyValuePair("filter" , "Filter"), + new KeyValuePair("fire" , "Fire"), + new KeyValuePair("fire-extinguisher" , "Fire Extinguisher"), + new KeyValuePair("flask" , "Flask"), + new KeyValuePair("frown-o" , "Frown"), + new KeyValuePair("gamepad" , "Gamepad"), + new KeyValuePair("gift" , "Gift"), + new KeyValuePair("glass" , "Glass"), + new KeyValuePair("globe" , "Globe"), + new KeyValuePair("hand-o-down" , "Hand Down"), + new KeyValuePair("hand-o-left" , "Hand Left"), + new KeyValuePair("hand-o-right" , "Hand Right"), + new KeyValuePair("hand-o-up" , "Hand Up"), + new KeyValuePair("hdd-o" , "Hdd"), + new KeyValuePair("heart" , "Heart"), + new KeyValuePair("home" , "Home"), + new KeyValuePair("info" , "Info"), + new KeyValuePair("key" , "Key"), + new KeyValuePair("keyboard-o" , "Keyboard"), + new KeyValuePair("laptop" , "Laptop"), + new KeyValuePair("leaf" , "Leaf"), + new KeyValuePair("legal" , "Legal"), + new KeyValuePair("lightbulb-o" , "Lightbulb"), + new KeyValuePair("linux" , "Linux"), + new KeyValuePair("location-arrow" , "Location Arrow"), + new KeyValuePair("magnet" , "Magnet"), + new KeyValuePair("male" , "Male"), + new KeyValuePair("map-marker" , "Map Marker"), + new KeyValuePair("medkit" , "Medkit"), + new KeyValuePair("meh-o" , "Meh"), + new KeyValuePair("microphone" , "Microphone"), + new KeyValuePair("microphone-slash" , "Microphone Slash"), + new KeyValuePair("minus-circle" , "Minus Circle"), + new KeyValuePair("mobile" , "Mobile"), + new KeyValuePair("money" , "Money"), + new KeyValuePair("moon-o" , "Moon"), + new KeyValuePair("music" , "Music"), + new KeyValuePair("paperclip" , "Paperclip"), + new KeyValuePair("pencil" , "Pencil"), + new KeyValuePair("phone" , "Phone"), + new KeyValuePair("picture-o" , "Picture"), + new KeyValuePair("plane" , "Plane"), + new KeyValuePair("power-off" , "Power Off"), + new KeyValuePair("print" , "Print"), + new KeyValuePair("puzzle-piece" , "Puzzle Piece"), + new KeyValuePair("question" , "Question"), + new KeyValuePair("question-circle" , "Question Circle"), + new KeyValuePair("random" , "Random"), + new KeyValuePair("retweet" , "Retweet"), + new KeyValuePair("road" , "Road"), + new KeyValuePair("rocket" , "Rocket"), + new KeyValuePair("shield" , "Shield"), + new KeyValuePair("shopping-cart" , "Shopping Cart"), + new KeyValuePair("smile-o" , "Smile"), + new KeyValuePair("star" , "Star"), + new KeyValuePair("suitcase" , "Suitcase"), + new KeyValuePair("sun-o" , "Sun"), + new KeyValuePair("tablet" , "Tablet"), + new KeyValuePair("tachometer" , "Tachometer"), + new KeyValuePair("tasks" , "Tasks"), + new KeyValuePair("thumbs-down" , "Thumbs Down"), + new KeyValuePair("thumbs-o-down" , "Thumbs Down"), + new KeyValuePair("thumbs-o-up" , "Thumbs Up"), + new KeyValuePair("thumbs-up" , "Thumbs Up"), + new KeyValuePair("thumb-tack" , "Thumb Tack"), + new KeyValuePair("trash-o" , "Trash"), + new KeyValuePair("trophy" , "Trophy"), + new KeyValuePair("truck" , "Truck"), + new KeyValuePair("umbrella" , "Umbrella"), + new KeyValuePair("wheelchair" , "Wheelchair"), + new KeyValuePair("windows" , "Windows"), + new KeyValuePair("wrench" , "Wrench") + }.AsReadOnly(); + } + + // Icon Colours + if (this._IconColourCache == null) + { + this._IconColourCache = new List>(){ + new KeyValuePair("lime" , "Lime"), + new KeyValuePair("green" , "Green"), + new KeyValuePair("emerald" , "Emerald"), + new KeyValuePair("teal" , "Teal"), + new KeyValuePair("cyan" , "Cyan"), + new KeyValuePair("cobalt" , "Cobalt"), + new KeyValuePair("indigo" , "Indigo"), + new KeyValuePair("violet" , "Violet"), + new KeyValuePair("pink" , "Pink"), + new KeyValuePair("magenta" , "Magenta"), + new KeyValuePair("crimson" , "Crimson"), + new KeyValuePair("red" , "Red"), + new KeyValuePair("orange" , "Orange"), + new KeyValuePair("amber" , "Amber"), + new KeyValuePair("yellow" , "Yellow"), + new KeyValuePair("brown" , "Brown"), + new KeyValuePair("olive" , "Olive"), + new KeyValuePair("steel" , "Steel"), + new KeyValuePair("mauve" , "Mauve"), + new KeyValuePair("sienna" , "Sienna") + }.AsReadOnly(); + } + + // SLA Options + if (this._SlaOptions == null) + { + this._SlaOptions = new List>() + { + new KeyValuePair(0, ""), + new KeyValuePair(15, "15 minutes"), + new KeyValuePair(30, "30 minutes"), + new KeyValuePair(60, "1 hour"), + new KeyValuePair(60 * 2, "2 hours"), + new KeyValuePair(60 * 4, "4 hours"), + new KeyValuePair(60 * 8, "8 hours"), + new KeyValuePair(60 * 24, "1 day"), + new KeyValuePair(60 * 24 * 2, "2 days"), + new KeyValuePair(60 * 24 * 3, "3 days"), + new KeyValuePair(60 * 24 * 4, "4 days"), + new KeyValuePair(60 * 24 * 5, "5 days"), + new KeyValuePair(60 * 24 * 6, "6 days"), + new KeyValuePair(60 * 24 * 7, "1 week"), + new KeyValuePair(60 * 24 * 7 * 2, "2 weeks"), + new KeyValuePair(60 * 24 * 7 * 3, "3 weeks"), + new KeyValuePair(60 * 24 * 7 * 4, "4 weeks"), + new KeyValuePair(60 * 24 * 7 * 4 * 2, "2 months"), + new KeyValuePair(60 * 24 * 7 * 4 * 3, "3 months"), + new KeyValuePair(60 * 24 * 7 * 4 * 4, "4 months"), + new KeyValuePair(60 * 24 * 7 * 4 * 5, "5 months"), + new KeyValuePair(60 * 24 * 7 * 4 * 6, "6 months") + }.AsReadOnly(); + } + #endregion + } + private void CalculateSubjectCache() + { + _SubjectCache = (from c in _Cache.Values.ToList() + from s in c.SubjectIds + group c by s into subjectId + select subjectId).ToDictionary(g => g.Key.ToLower(), g => g.ToList()); + } + + public ReadOnlyCollection> Icons { get { return this._Icons; } } + public ReadOnlyCollection> IconColours { get { return this._IconColourCache; } } + public ReadOnlyCollection> SlaOptions { get { return this._SlaOptions; } } + + public JobQueueToken UpdateQueue(JobQueue JobQueue) + { + var token = JobQueueToken.FromJobQueue(JobQueue); + JobQueueToken existingToken; + + if (_Cache.TryGetValue(JobQueue.Id, out existingToken)) + { + if (_Cache.TryUpdate(JobQueue.Id, token, existingToken)) + { + if (existingToken.JobQueue.SubjectIds != token.JobQueue.SubjectIds) + CalculateSubjectCache(); + + return token; + } + else + return null; + } + else + { + if (_Cache.TryAdd(JobQueue.Id, token)) + { + CalculateSubjectCache(); + return token; + } + else + return null; + } + } + public bool RemoveQueue(int JobQueueId) + { + JobQueueToken token; + if (_Cache.TryRemove(JobQueueId, out token)) + { + CalculateSubjectCache(); + return true; + } + else + { + return false; + } + } + public JobQueueToken GetQueue(int JobQueueId) + { + JobQueueToken token; + if (_Cache.TryGetValue(JobQueueId, out token)) + return token; + else + return null; + } + public ReadOnlyCollection GetQueues() + { + return _Cache.Values.ToList().AsReadOnly(); + } + private IEnumerable GetQueuesForSubject(string SubjectId) + { + List tokens; + if (_SubjectCache.TryGetValue(SubjectId.ToLower(), out tokens)) + return tokens; + else + return Enumerable.Empty(); + } + public ReadOnlyCollection GetQueuesForSubject(IEnumerable SubjectIds) + { + return SubjectIds.SelectMany(sid => GetQueuesForSubject(sid)).Distinct().ToList().AsReadOnly(); + } + + public void ReInitializeCache(DiscoDataContext Database) + { + Initialize(Database); + } + } +} diff --git a/Disco.Services/Jobs/JobQueues/JobQueueDeleteTask.cs b/Disco.Services/Jobs/JobQueues/JobQueueDeleteTask.cs new file mode 100644 index 00000000..795489cd --- /dev/null +++ b/Disco.Services/Jobs/JobQueues/JobQueueDeleteTask.cs @@ -0,0 +1,39 @@ +using Disco.Data.Repository; +using Disco.Services.Tasks; +using Quartz; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Disco.Services.Jobs.JobQueues +{ + public class JobQueueDeleteTask : ScheduledTask + { + public override string TaskName { get { return "Job Queues - Delete Queue"; } } + + public override bool SingleInstanceTask { get { return false; }} + public override bool CancelInitiallySupported { get { return false; } } + public override bool LogExceptionsOnly { get { return true; } } + + protected override void ExecuteTask() + { + int jobQueueId = (int)this.ExecutionContext.JobDetail.JobDataMap["JobQueueId"]; + + using (DiscoDataContext Database = new DiscoDataContext()) + { + JobQueueService.DeleteJobQueue(Database, jobQueueId, this.Status); + } + } + + public static ScheduledTaskStatus ScheduleNow(int JobQueueId) + { + JobDataMap taskData = new JobDataMap() { { "JobQueueId", JobQueueId } }; + + var instance = new JobQueueDeleteTask(); + + return instance.ScheduleTask(taskData); + } + } +} diff --git a/Disco.Services/Jobs/JobQueues/JobQueueService.cs b/Disco.Services/Jobs/JobQueues/JobQueueService.cs new file mode 100644 index 00000000..394f813c --- /dev/null +++ b/Disco.Services/Jobs/JobQueues/JobQueueService.cs @@ -0,0 +1,187 @@ +using Disco.Data.Repository; +using Disco.Models.Repository; +using Disco.Services.Authorization; +using Disco.Services.Tasks; +using Disco.Services.Users; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web; + +namespace Disco.Services.Jobs.JobQueues +{ + public static class JobQueueService + { + private const string _cacheHttpRequestKey = "Disco_UserQueuesToken_{0}"; + private static Cache _cache; + + public static void Initialize(DiscoDataContext Database) + { + _cache = new Cache(Database); + } + + public static ReadOnlyCollection> IconColours { get { return _cache.IconColours; } } + public static ReadOnlyCollection> Icons { get { return _cache.Icons; } } + public static ReadOnlyCollection> SlaOptions { get { return _cache.SlaOptions; } } + + public static ReadOnlyCollection GetQueues() { return _cache.GetQueues(); } + public static JobQueueToken GetQueue(int JobQueueId) { return _cache.GetQueue(JobQueueId); } + + #region Job Queues Maintenance + public static JobQueueToken CreateJobQueue(DiscoDataContext Database, JobQueue JobQueue) + { + // Verify + if (string.IsNullOrWhiteSpace(JobQueue.Name)) + throw new ArgumentException("The Job Queue Name is required"); + if (string.IsNullOrWhiteSpace(JobQueue.Description)) + throw new ArgumentException("The Job Queue Description is required"); + + // Name Unique + if (_cache.GetQueues().Count(q => q.JobQueue.Name == JobQueue.Name) > 0) + throw new ArgumentException("Another Job Queue already exists with that name", "JobQueue"); + + // Clone to break reference + var queue = new JobQueue() + { + Name = JobQueue.Name, + Description = JobQueue.Description, + Icon = JobQueue.Icon, + IconColour = JobQueue.IconColour, + DefaultSLAExpiry = JobQueue.DefaultSLAExpiry, + Priority = JobQueue.Priority, + SubjectIds = JobQueue.SubjectIds + }; + + Database.JobQueues.Add(queue); + Database.SaveChanges(); + + return _cache.UpdateQueue(queue); + } + public static JobQueueToken UpdateJobQueue(DiscoDataContext Database, JobQueue JobQueue) + { + // Verify + if (string.IsNullOrWhiteSpace(JobQueue.Name)) + throw new ArgumentException("The Job Queue Name is required"); + if (string.IsNullOrWhiteSpace(JobQueue.Description)) + throw new ArgumentException("The Job Queue Description is required"); + + // Name Unique + if (_cache.GetQueues().Count(q => q.JobQueue.Id != JobQueue.Id && q.JobQueue.Name == JobQueue.Name) > 0) + throw new ArgumentException("Another Job Queue already exists with that name", "JobQueue"); + + Database.SaveChanges(); + + return _cache.UpdateQueue(JobQueue); + } + public static void DeleteJobQueue(DiscoDataContext Database, int JobQueueId, ScheduledTaskStatus Status) + { + JobQueue queue = Database.JobQueues.Find(JobQueueId); + + // Validate: Current Jobs? + int currentJobCount = Database.JobQueueJobs.Count(jqj => jqj.JobQueueId == queue.Id && jqj.RemovedDate.HasValue); + if (currentJobCount > 0) + throw new InvalidOperationException("The Job Queue cannot be deleted because it contains jobs"); + + // Delete History + Status.UpdateStatus(0, string.Format("Removing '{0}' [{1}] Job Queue", queue.Name, queue.Id), "Starting"); + var jobQueueJobs = Database.JobQueueJobs.Include("Job").Where(jsj => jsj.JobQueueId == queue.Id).ToList(); + if (jobQueueJobs.Count > 0) + { + double progressInterval = 90 / jobQueueJobs.Count; + for (int jqjIndex = 0; jqjIndex < jobQueueJobs.Count; jqjIndex++) + { + var jqj = jobQueueJobs[jqjIndex]; + + Status.UpdateStatus(jqjIndex * progressInterval, string.Format("Merging history into job #{0} logs", jqj.JobId)); + + // Write Logs + Database.JobLogs.Add(new JobLog() + { + JobId = jqj.JobId, + TechUserId = jqj.AddedUserId, + Timestamp = jqj.AddedDate, + Comments = string.Format("Added to Job Queue: {1}{0}Priority: {2}{0}Comment: {3}", Environment.NewLine, queue.Name, jqj.Priority.ToString(), string.IsNullOrWhiteSpace(jqj.AddedComment) ? "" : jqj.AddedComment) + }); + Database.JobLogs.Add(new JobLog() + { + JobId = jqj.JobId, + TechUserId = jqj.RemovedUserId, + Timestamp = jqj.RemovedDate.Value, + Comments = string.Format("Removed from Job Queue: {1}{0}Comment: {2}", Environment.NewLine, queue.Name, string.IsNullOrWhiteSpace(jqj.RemovedComment) ? "" : jqj.RemovedComment) + }); + + // Delete JQJ + Database.JobQueueJobs.Remove(jqj); + + // Save Changes + Database.SaveChanges(); + } + } + + // Delete Queue + Status.UpdateStatus(90, "Deleting Queue"); + Database.JobQueues.Remove(queue); + Database.SaveChanges(); + + // Remove from Cache + _cache.RemoveQueue(JobQueueId); + + Status.Finished(string.Format("Successfully Deleted Job Queue: '{0}' [{1}]", queue.Name, queue.Id)); + } + #endregion + + public static ReadOnlyCollection UsersQueues(User User) + { + return UsersQueues(User.Id); + } + public static ReadOnlyCollection UsersQueues(string UserId) + { + var userAuth = UserService.GetAuthorization(UserId); + + return UsersQueues(userAuth); + } + public static ReadOnlyCollection UsersQueues(AuthorizationToken UserAuthorization) + { + string cacheKey = string.Format(_cacheHttpRequestKey, UserAuthorization.User.Id); + ReadOnlyCollection tokens = null; + + // Check for ASP.NET + if (HttpContext.Current != null) + { + tokens = (ReadOnlyCollection)HttpContext.Current.Items[_cacheHttpRequestKey]; + } + + if (tokens == null) + { + var subjectIds = (new string[] { UserAuthorization.User.Id }).Concat(UserAuthorization.GroupMembership); + tokens = _cache.GetQueuesForSubject(subjectIds); + + HttpContext.Current.Items[_cacheHttpRequestKey] = tokens; + } + + return tokens; + } + + public static string RandomIcon() + { + var rnd = new Random(); + var unusedIcons = _cache.Icons.Select(i => i.Key).Except(_cache.GetQueues().Select(q => q.JobQueue.Icon)).ToList(); + if (unusedIcons.Count > 0) + return unusedIcons[rnd.Next(unusedIcons.Count - 1)]; + else + return _cache.Icons[rnd.Next(_cache.Icons.Count - 1)].Key; + } + public static string RandomIconColour() + { + var rnd = new Random(); + var unusedColours = _cache.IconColours.Select(i => i.Key).Except(_cache.GetQueues().Select(q => q.JobQueue.IconColour)).ToList(); + if (unusedColours.Count > 0) + return unusedColours[rnd.Next(unusedColours.Count - 1)]; + else + return _cache.IconColours[rnd.Next(_cache.IconColours.Count - 1)].Key; + } + } +} diff --git a/Disco.Services/Jobs/JobQueues/JobQueueToken.cs b/Disco.Services/Jobs/JobQueues/JobQueueToken.cs new file mode 100644 index 00000000..ad316626 --- /dev/null +++ b/Disco.Services/Jobs/JobQueues/JobQueueToken.cs @@ -0,0 +1,27 @@ +using Disco.Models.Repository; +using Disco.Models.Services.Jobs.JobQueues; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace Disco.Services.Jobs.JobQueues +{ + public class JobQueueToken : IJobQueueToken + { + public JobQueue JobQueue { get; private set; } + internal HashSet SubjectIdHashes { get; private set; } + public ReadOnlyCollection SubjectIds { get; private set; } + + public static JobQueueToken FromJobQueue(JobQueue JobQueue) + { + string[] sg = (JobQueue.SubjectIds == null ? new string[0] : JobQueue.SubjectIds.Split(',').ToArray()); + + return new JobQueueToken() + { + JobQueue = JobQueue, + SubjectIdHashes = new HashSet(sg.Select(i => i.ToLower())), + SubjectIds = sg.ToList().AsReadOnly() + }; + } + } +} diff --git a/Disco.Services/Properties/AssemblyInfo.cs b/Disco.Services/Properties/AssemblyInfo.cs index 89fbf121..9e180ac3 100644 --- a/Disco.Services/Properties/AssemblyInfo.cs +++ b/Disco.Services/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.1128.1503")] -[assembly: AssemblyFileVersion("1.2.1128.1503")] \ No newline at end of file +[assembly: AssemblyVersion("1.2.1229.1537")] +[assembly: AssemblyFileVersion("1.2.1229.1537")] \ No newline at end of file diff --git a/Disco.Services/Tasks/ScheduledTaskStatus.cs b/Disco.Services/Tasks/ScheduledTaskStatus.cs index 2e1a138b..792cae44 100644 --- a/Disco.Services/Tasks/ScheduledTaskStatus.cs +++ b/Disco.Services/Tasks/ScheduledTaskStatus.cs @@ -264,6 +264,10 @@ namespace Disco.Services.Tasks { Finished(this._finishedMessage, this._finishedUrl); } + public void Finished(string FinishedMessage) + { + Finished(FinishedMessage, this._finishedUrl); + } public void Finished(string FinishedMessage, string FinishedUrl) { List changedProperties = new List() { "IsRunning", "FinishedTimestamp" }; diff --git a/Disco.Services/packages.config b/Disco.Services/packages.config index 71cc84df..48bd73cf 100644 --- a/Disco.Services/packages.config +++ b/Disco.Services/packages.config @@ -11,6 +11,11 @@ + + + + + \ No newline at end of file diff --git a/Disco.Web.Extensions/DataModelExtension/JobSubTypeExtensions.cs b/Disco.Web.Extensions/DataModelExtension/JobSubTypeExtensions.cs index e3d951e3..141c3596 100644 --- a/Disco.Web.Extensions/DataModelExtension/JobSubTypeExtensions.cs +++ b/Disco.Web.Extensions/DataModelExtension/JobSubTypeExtensions.cs @@ -9,22 +9,39 @@ namespace Disco.Web.Extensions { public static class JobSubTypeExtensions { - public static List ToSelectListItems(this IEnumerable jobSubTypes, List SelectedItems) + public static List ToSelectListItems(this IEnumerable jobSubTypes, IEnumerable SelectedItems, bool IncludeQueueIcons = false) { List selectedIds = default(List); - + if (SelectedItems != null) selectedIds = SelectedItems.Select(i => string.Format("{0}_{1}", i.JobTypeId, i.Id)).ToList(); return jobSubTypes.ToSelectListItems(selectedIds); } - public static List ToSelectListItems(this IEnumerable jobSubTypes, List SelectedIds = null) + public static List ToSelectListItems(this IEnumerable jobSubTypes, List SelectedIds = null, bool IncludeQueueIcons = false) { if (SelectedIds == null) - return jobSubTypes.Select(jst => new SelectListItem { Value = string.Format("{0}_{1}", jst.JobTypeId, jst.Id), Text = jst.Description }).ToList(); + return jobSubTypes.Select(jst => new SelectListItem { Value = string.Format("{0}_{1}", jst.JobTypeId, jst.Id), Text = IncludeQueueIcons ? jst.DescriptionWithIcons() : jst.Description }).ToList(); else - return jobSubTypes.Select(jst => new SelectListItem { Value = string.Format("{0}_{1}", jst.JobTypeId, jst.Id), Text = jst.Description, Selected = (SelectedIds.Contains(string.Format("{0}_{1}", jst.JobTypeId, jst.Id))) }).ToList(); + return jobSubTypes.Select(jst => new SelectListItem { Value = string.Format("{0}_{1}", jst.JobTypeId, jst.Id), Text = IncludeQueueIcons ? jst.DescriptionWithIcons() : jst.Description, Selected = (SelectedIds.Contains(string.Format("{0}_{1}", jst.JobTypeId, jst.Id))) }).ToList(); + } + + public static string DescriptionWithIcons(this JobSubType jst) + { + if (jst.JobQueues.Count > 0) + { + var sb = new System.Text.StringBuilder(System.Web.HttpUtility.HtmlEncode(jst.Description)); + + foreach (var jq in jst.JobQueues) + sb.AppendFormat(" ", jq.Icon, jq.IconColour, jq.Name); + + return sb.ToString(); + } + else + { + return System.Web.HttpUtility.HtmlEncode(jst.Description); + } } } } diff --git a/Disco.Web.Extensions/DataModelExtension/JobTypeExtensions.cs b/Disco.Web.Extensions/DataModelExtension/JobTypeExtensions.cs index 09d720d3..170ee3ab 100644 --- a/Disco.Web.Extensions/DataModelExtension/JobTypeExtensions.cs +++ b/Disco.Web.Extensions/DataModelExtension/JobTypeExtensions.cs @@ -27,7 +27,7 @@ namespace Disco.Web.Extensions return jobTypes.Select(jt => new SelectListItem { Value = jt.Id, Text = jt.Description, Selected = (SelectedId == jt.Id) }).ToList(); } - public static List ToSelectListItems(this IEnumerable jobTypes, List SelectedItems) + public static List ToSelectListItems(this IEnumerable jobTypes, IEnumerable SelectedItems) { List selectedIds = default(List); diff --git a/Disco.Web.Extensions/Properties/AssemblyInfo.cs b/Disco.Web.Extensions/Properties/AssemblyInfo.cs index 7f960e1e..933447a3 100644 --- a/Disco.Web.Extensions/Properties/AssemblyInfo.cs +++ b/Disco.Web.Extensions/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.1128.1503")] -[assembly: AssemblyFileVersion("1.2.1128.1503")] \ No newline at end of file +[assembly: AssemblyVersion("1.2.1229.1537")] +[assembly: AssemblyFileVersion("1.2.1229.1537")] \ No newline at end of file diff --git a/Disco.Web/App_Code/CommonHelpers.cshtml b/Disco.Web/App_Code/CommonHelpers.cshtml index f3fe5b13..fda72764 100644 --- a/Disco.Web/App_Code/CommonHelpers.cshtml +++ b/Disco.Web/App_Code/CommonHelpers.cshtml @@ -6,19 +6,19 @@ @using System.Web.Mvc @using System.Web.Mvc.Html; @using Disco.Services.Web; -@helper FriendlyDate(DateTime d, string ElementId = null) -{@d.FromNow()} -@helper FriendlyDate(DateTime? d, string NullValue = "n/a", string ElementId = null) -{@d.FromNow(NullValue)} +@helper FriendlyDate(DateTime d, string ElementId = null, bool WithoutSuffix = false) +{@d.FromNow(WithoutSuffix)} +@helper FriendlyDate(DateTime? d, string NullValue = "n/a", string ElementId = null, bool WithoutSuffix = false) +{@d.FromNow(WithoutSuffix, NullValue)} @helper RadioButtonList(string id, List items, int columns = 1) { @ItemList("radio", id, items, columns) } -@helper CheckBoxList(string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null) +@helper CheckBoxList(string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) { - @ItemList("checkbox", id, items, columns, alignEven, forceUniqueIds) + @ItemList("checkbox", id, items, columns, alignEven, forceUniqueIds, htmlEncodeText) } -@helper ItemList(string inputType, string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null) +@helper ItemList(string inputType, string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) { int itemsPerColumn = items.Count / columns; int columnWidth = (100 / columns); @@ -37,7 +37,10 @@ itemNextId++; var itemId = forceUniqueIds.HasValue ? string.Format("{0}_{1}_{2}", id, item.Value, forceUniqueIds++) : string.Format("{0}_{1}", id, item.Value);
  • -
  • + } } @@ -46,23 +49,23 @@ } -@helper FriendlyDateAndUser(DateTime? d, User u, string DateNullValue = "n/a") +@helper FriendlyDateAndUser(DateTime? d, User u, string DateNullValue = "n/a", bool WithoutSuffix = false) { - @FriendlyDate(d, DateNullValue); - @FriendlyUser(u, null, "by"); + @FriendlyDate(d, DateNullValue, WithoutSuffix: WithoutSuffix); + @FriendlyUser(u, null, " by"); } -@helper FriendlyDateAndUser(DateTime d, User u) +@helper FriendlyDateAndUser(DateTime d, User u, bool WithoutSuffix = false) { - @FriendlyDate(d); - @FriendlyUser(u, null, "by"); + @FriendlyDate(d, WithoutSuffix: WithoutSuffix); + @FriendlyUser(u, null, " by"); } -@helper FriendlyDateAndTitleUser(DateTime? d, User u, string DateNullValue = "n/a") +@helper FriendlyDateAndTitleUser(DateTime? d, User u, string DateNullValue = "n/a", bool WithoutSuffix = false) { - @d.FromNow(DateNullValue) + @d.FromNow(WithoutSuffix, DateNullValue) } -@helper FriendlyDateAndTitleUser(DateTime d, User u) +@helper FriendlyDateAndTitleUser(DateTime d, User u, bool WithoutSuffix = false) { - @d.FromNow() + @d.FromNow(WithoutSuffix) } @helper FriendlyUser(User u, string nullValue = null, string prepend = null) { diff --git a/Disco.Web/App_Code/CommonHelpers.generated.cs b/Disco.Web/App_Code/CommonHelpers.generated.cs index 8e2f0729..7d2f1d22 100644 --- a/Disco.Web/App_Code/CommonHelpers.generated.cs +++ b/Disco.Web/App_Code/CommonHelpers.generated.cs @@ -70,7 +70,7 @@ namespace Disco.Web public class CommonHelpers : System.Web.WebPages.HelperPage { -public static System.Web.WebPages.HelperResult FriendlyDate(DateTime d, string ElementId = null) +public static System.Web.WebPages.HelperResult FriendlyDate(DateTime d, string ElementId = null, bool WithoutSuffix = false) { return new System.Web.WebPages.HelperResult(__razor_helper_writer => { @@ -121,7 +121,7 @@ WriteLiteralTo(@__razor_helper_writer, "\" class=\"date nowrap\">"); #line 10 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, d.FromNow()); + WriteTo(@__razor_helper_writer, d.FromNow(WithoutSuffix)); #line default #line hidden @@ -131,16 +131,16 @@ WriteLiteralTo(@__razor_helper_writer, ""); #line 10 "..\..\App_Code\CommonHelpers.cshtml" - + #line default #line hidden }); - } + } -public static System.Web.WebPages.HelperResult FriendlyDate(DateTime? d, string NullValue = "n/a", string ElementId = null) +public static System.Web.WebPages.HelperResult FriendlyDate(DateTime? d, string NullValue = "n/a", string ElementId = null, bool WithoutSuffix = false) { return new System.Web.WebPages.HelperResult(__razor_helper_writer => { @@ -191,7 +191,7 @@ WriteLiteralTo(@__razor_helper_writer, "\" class=\"date nowrap\">"); #line 12 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, d.FromNow(NullValue)); + WriteTo(@__razor_helper_writer, d.FromNow(WithoutSuffix, NullValue)); #line default #line hidden @@ -201,13 +201,13 @@ WriteLiteralTo(@__razor_helper_writer, ""); #line 12 "..\..\App_Code\CommonHelpers.cshtml" - + #line default #line hidden }); - } + } public static System.Web.WebPages.HelperResult RadioButtonList(string id, List items, int columns = 1) @@ -241,7 +241,7 @@ WriteTo(@__razor_helper_writer, ItemList("radio", id, items, columns)); } -public static System.Web.WebPages.HelperResult CheckBoxList(string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null) +public static System.Web.WebPages.HelperResult CheckBoxList(string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) { return new System.Web.WebPages.HelperResult(__razor_helper_writer => { @@ -255,14 +255,14 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { #line 19 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, ItemList("checkbox", id, items, columns, alignEven, forceUniqueIds)); +WriteTo(@__razor_helper_writer, ItemList("checkbox", id, items, columns, alignEven, forceUniqueIds, htmlEncodeText)); #line default #line hidden #line 19 "..\..\App_Code\CommonHelpers.cshtml" - + #line default #line hidden @@ -272,7 +272,7 @@ WriteTo(@__razor_helper_writer, ItemList("checkbox", id, items, columns, alignEv } -public static System.Web.WebPages.HelperResult ItemList(string inputType, string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null) +public static System.Web.WebPages.HelperResult ItemList(string inputType, string id, List items, int columns = 1, bool alignEven = true, int? forceUniqueIds = null, bool htmlEncodeText = true) { return new System.Web.WebPages.HelperResult(__razor_helper_writer => { @@ -384,21 +384,54 @@ WriteLiteralTo(@__razor_helper_writer, "/>\r\n"); -#line 41 "..\..\App_Code\CommonHelpers.cshtml" +#line 44 "..\..\App_Code\CommonHelpers.cshtml" } @@ -409,7 +442,7 @@ WriteLiteralTo(@__razor_helper_writer, " \r\n -#line 45 "..\..\App_Code\CommonHelpers.cshtml" +#line 48 "..\..\App_Code\CommonHelpers.cshtml" } #line default @@ -419,7 +452,7 @@ WriteLiteralTo(@__razor_helper_writer, " \r\n \r\n"); -#line 48 "..\..\App_Code\CommonHelpers.cshtml" +#line 51 "..\..\App_Code\CommonHelpers.cshtml" #line default #line hidden @@ -429,87 +462,42 @@ WriteLiteralTo(@__razor_helper_writer, " \r\n \r\n"); } -public static System.Web.WebPages.HelperResult FriendlyDateAndUser(DateTime? d, User u, string DateNullValue = "n/a") +public static System.Web.WebPages.HelperResult FriendlyDateAndUser(DateTime? d, User u, string DateNullValue = "n/a", bool WithoutSuffix = false) { return new System.Web.WebPages.HelperResult(__razor_helper_writer => { -#line 50 "..\..\App_Code\CommonHelpers.cshtml" +#line 53 "..\..\App_Code\CommonHelpers.cshtml" #line default #line hidden -#line 51 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyDate(d, DateNullValue)); +#line 54 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(@__razor_helper_writer, FriendlyDate(d, DateNullValue, WithoutSuffix: WithoutSuffix)); #line default #line hidden -#line 51 "..\..\App_Code\CommonHelpers.cshtml" - ; +#line 54 "..\..\App_Code\CommonHelpers.cshtml" + ; #line default #line hidden -#line 52 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyUser(u, null, "by")); - -#line default -#line hidden - - -#line 52 "..\..\App_Code\CommonHelpers.cshtml" - ; - -#line default -#line hidden - -}); - -} - - -public static System.Web.WebPages.HelperResult FriendlyDateAndUser(DateTime d, User u) -{ -return new System.Web.WebPages.HelperResult(__razor_helper_writer => { - - - #line 55 "..\..\App_Code\CommonHelpers.cshtml" - - -#line default -#line hidden - - -#line 56 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyDate(d)); +WriteTo(@__razor_helper_writer, FriendlyUser(u, null, " by")); #line default #line hidden -#line 56 "..\..\App_Code\CommonHelpers.cshtml" - ; - -#line default -#line hidden - - -#line 57 "..\..\App_Code\CommonHelpers.cshtml" -WriteTo(@__razor_helper_writer, FriendlyUser(u, null, "by")); - -#line default -#line hidden - - -#line 57 "..\..\App_Code\CommonHelpers.cshtml" - ; +#line 55 "..\..\App_Code\CommonHelpers.cshtml" + ; #line default #line hidden @@ -519,13 +507,58 @@ WriteTo(@__razor_helper_writer, FriendlyUser(u, null, "by")); } -public static System.Web.WebPages.HelperResult FriendlyDateAndTitleUser(DateTime? d, User u, string DateNullValue = "n/a") +public static System.Web.WebPages.HelperResult FriendlyDateAndUser(DateTime d, User u, bool WithoutSuffix = false) { return new System.Web.WebPages.HelperResult(__razor_helper_writer => { +#line 58 "..\..\App_Code\CommonHelpers.cshtml" + + +#line default +#line hidden + + +#line 59 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(@__razor_helper_writer, FriendlyDate(d, WithoutSuffix: WithoutSuffix)); + +#line default +#line hidden + + +#line 59 "..\..\App_Code\CommonHelpers.cshtml" + ; + +#line default +#line hidden + + #line 60 "..\..\App_Code\CommonHelpers.cshtml" +WriteTo(@__razor_helper_writer, FriendlyUser(u, null, " by")); + +#line default +#line hidden + + +#line 60 "..\..\App_Code\CommonHelpers.cshtml" + ; + +#line default +#line hidden + +}); + +} + + +public static System.Web.WebPages.HelperResult FriendlyDateAndTitleUser(DateTime? d, User u, string DateNullValue = "n/a", bool WithoutSuffix = false) +{ +return new System.Web.WebPages.HelperResult(__razor_helper_writer => { + + + +#line 63 "..\..\App_Code\CommonHelpers.cshtml" #line default @@ -535,7 +568,7 @@ WriteLiteralTo(@__razor_helper_writer, " "); -#line 61 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, d.FromNow(DateNullValue)); +#line 64 "..\..\App_Code\CommonHelpers.cshtml" + WriteTo(@__razor_helper_writer, d.FromNow(WithoutSuffix, DateNullValue)); #line default #line hidden @@ -575,7 +608,7 @@ WriteLiteralTo(@__razor_helper_writer, "\r\n"); -#line 62 "..\..\App_Code\CommonHelpers.cshtml" +#line 65 "..\..\App_Code\CommonHelpers.cshtml" #line default #line hidden @@ -585,13 +618,13 @@ WriteLiteralTo(@__razor_helper_writer, "\r\n"); } -public static System.Web.WebPages.HelperResult FriendlyDateAndTitleUser(DateTime d, User u) +public static System.Web.WebPages.HelperResult FriendlyDateAndTitleUser(DateTime d, User u, bool WithoutSuffix = false) { return new System.Web.WebPages.HelperResult(__razor_helper_writer => { -#line 64 "..\..\App_Code\CommonHelpers.cshtml" +#line 67 "..\..\App_Code\CommonHelpers.cshtml" #line default @@ -601,7 +634,7 @@ WriteLiteralTo(@__razor_helper_writer, " "); -#line 65 "..\..\App_Code\CommonHelpers.cshtml" - WriteTo(@__razor_helper_writer, d.FromNow()); +#line 68 "..\..\App_Code\CommonHelpers.cshtml" + WriteTo(@__razor_helper_writer, d.FromNow(WithoutSuffix)); #line default #line hidden @@ -641,7 +674,7 @@ WriteLiteralTo(@__razor_helper_writer, "\r\n"); -#line 66 "..\..\App_Code\CommonHelpers.cshtml" +#line 69 "..\..\App_Code\CommonHelpers.cshtml" #line default #line hidden @@ -657,7 +690,7 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { -#line 68 "..\..\App_Code\CommonHelpers.cshtml" +#line 71 "..\..\App_Code\CommonHelpers.cshtml" if (u != null) { @@ -666,7 +699,7 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { #line hidden -#line 71 "..\..\App_Code\CommonHelpers.cshtml" +#line 74 "..\..\App_Code\CommonHelpers.cshtml" WriteTo(@__razor_helper_writer, prepend); #line default @@ -677,7 +710,7 @@ WriteLiteralTo(@__razor_helper_writer, " "); -#line 71 "..\..\App_Code\CommonHelpers.cshtml" +#line 74 "..\..\App_Code\CommonHelpers.cshtml" WriteTo(@__razor_helper_writer, u.Id); #line default @@ -697,7 +730,7 @@ WriteLiteralTo(@__razor_helper_writer, "\r\n"); -#line 72 "..\..\App_Code\CommonHelpers.cshtml" +#line 75 "..\..\App_Code\CommonHelpers.cshtml" } else { @@ -709,7 +742,7 @@ WriteLiteralTo(@__razor_helper_writer, " "); -#line 75 "..\..\App_Code\CommonHelpers.cshtml" +#line 78 "..\..\App_Code\CommonHelpers.cshtml" WriteTo(@__razor_helper_writer, nullValue); #line default @@ -719,7 +752,7 @@ WriteLiteralTo(@__razor_helper_writer, "\r\n"); -#line 76 "..\..\App_Code\CommonHelpers.cshtml" +#line 79 "..\..\App_Code\CommonHelpers.cshtml" } #line default @@ -736,7 +769,7 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { -#line 79 "..\..\App_Code\CommonHelpers.cshtml" +#line 82 "..\..\App_Code\CommonHelpers.cshtml" for (int index = 0; index < BreadCrumbs.Count; index++) { @@ -751,7 +784,7 @@ WriteLiteralTo(@__razor_helper_writer, " >\r\n"); -#line 86 "..\..\App_Code\CommonHelpers.cshtml" +#line 89 "..\..\App_Code\CommonHelpers.cshtml" } if (breadCrumb.Item2 == null) { @@ -760,14 +793,14 @@ WriteLiteralTo(@__razor_helper_writer, " >\r\n"); #line hidden -#line 89 "..\..\App_Code\CommonHelpers.cshtml" +#line 92 "..\..\App_Code\CommonHelpers.cshtml" WriteTo(@__razor_helper_writer, breadCrumb.Item1); #line default #line hidden -#line 89 "..\..\App_Code\CommonHelpers.cshtml" +#line 92 "..\..\App_Code\CommonHelpers.cshtml" } else @@ -777,14 +810,14 @@ WriteTo(@__razor_helper_writer, breadCrumb.Item1); #line hidden -#line 93 "..\..\App_Code\CommonHelpers.cshtml" +#line 96 "..\..\App_Code\CommonHelpers.cshtml" WriteTo(@__razor_helper_writer, Html.GetPageHelper().ActionLink(breadCrumb.Item1, breadCrumb.Item2)); #line default #line hidden -#line 93 "..\..\App_Code\CommonHelpers.cshtml" +#line 96 "..\..\App_Code\CommonHelpers.cshtml" } } @@ -803,21 +836,21 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { -#line 98 "..\..\App_Code\CommonHelpers.cshtml" +#line 101 "..\..\App_Code\CommonHelpers.cshtml" #line default #line hidden -#line 99 "..\..\App_Code\CommonHelpers.cshtml" +#line 102 "..\..\App_Code\CommonHelpers.cshtml" WriteTo(@__razor_helper_writer, Title); #line default #line hidden -#line 99 "..\..\App_Code\CommonHelpers.cshtml" +#line 102 "..\..\App_Code\CommonHelpers.cshtml" #line default @@ -834,7 +867,7 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { -#line 102 "..\..\App_Code\CommonHelpers.cshtml" +#line 105 "..\..\App_Code\CommonHelpers.cshtml" for (int index = 0; index < BreadCrumbs.Count; index++) { @@ -846,14 +879,14 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { #line hidden -#line 108 "..\..\App_Code\CommonHelpers.cshtml" +#line 111 "..\..\App_Code\CommonHelpers.cshtml" WriteTo(@__razor_helper_writer, new HtmlString(" > ")); #line default #line hidden -#line 108 "..\..\App_Code\CommonHelpers.cshtml" +#line 111 "..\..\App_Code\CommonHelpers.cshtml" } @@ -861,14 +894,14 @@ WriteTo(@__razor_helper_writer, new HtmlString(" > ")); #line hidden -#line 110 "..\..\App_Code\CommonHelpers.cshtml" +#line 113 "..\..\App_Code\CommonHelpers.cshtml" WriteTo(@__razor_helper_writer, breadCrumb.Item1); #line default #line hidden -#line 110 "..\..\App_Code\CommonHelpers.cshtml" +#line 113 "..\..\App_Code\CommonHelpers.cshtml" } @@ -886,21 +919,21 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { -#line 114 "..\..\App_Code\CommonHelpers.cshtml" +#line 117 "..\..\App_Code\CommonHelpers.cshtml" #line default #line hidden -#line 115 "..\..\App_Code\CommonHelpers.cshtml" +#line 118 "..\..\App_Code\CommonHelpers.cshtml" WriteTo(@__razor_helper_writer, Title); #line default #line hidden -#line 115 "..\..\App_Code\CommonHelpers.cshtml" +#line 118 "..\..\App_Code\CommonHelpers.cshtml" #line default @@ -917,7 +950,7 @@ return new System.Web.WebPages.HelperResult(__razor_helper_writer => { -#line 118 "..\..\App_Code\CommonHelpers.cshtml" +#line 121 "..\..\App_Code\CommonHelpers.cshtml" Html.GetPageHelper().BundleDeferred("~/ClientScripts/Modules/Disco-jQueryExtensions"); #line default @@ -927,7 +960,7 @@ WriteLiteralTo(@__razor_helper_writer, " \r -#line 123 "..\..\App_Code\CommonHelpers.cshtml" +#line 126 "..\..\App_Code\CommonHelpers.cshtml" } else { @@ -970,7 +1003,7 @@ WriteLiteralTo(@__razor_helper_writer, " \r\n"); - #line 148 "..\..\Areas\Config\Views\Config\Index.cshtml" + #line 155 "..\..\Areas\Config\Views\Config\Index.cshtml" } diff --git a/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.cshtml b/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.cshtml index 6b1e53a2..5072339b 100644 --- a/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.cshtml +++ b/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.cshtml @@ -166,125 +166,143 @@ }); }); - var $trJobTypes = $('#trJobTypes'); - var $trJobTypeActions = $('#trJobTypeActions'); - var $jobTypes = $trJobTypes.find('input[type="checkbox"]'); - $jobTypes.change(jobTypesChange); + var $JobSubTypes = $('#Config_DocumentTemplates_JobSubTypes'); function scopeChange() { if ($scope.val() == 'Job') { - $trJobTypes.show(); - $trJobTypeActions.show(); - jobTypesChange(); + $JobSubTypes.slideDown('fast'); } else { - $trJobTypes.hide(); - $trJobTypeActions.hide(); - $jobTypes.filter(':checked').each(function () { - $(this).prop('checked', false); - }); - $('.jobSubTypes').hide().find('input[type="checkbox"]:checked').each(function () { - $(this).prop('checked', false); - }); + $JobSubTypes.slideUp('fast'); } } - - function jobTypesChange() { - $('.jobSubTypes').hide(); - $jobTypes.filter(':checked').each(function () { - $('#trJobSubType' + $(this).val()).show(); - }); - } - - $('#TypeAction_Save').click(function () { - var data = { SubTypes: [] }; - var $ajaxLoading = $('#TypeAction_Save').next('.ajaxLoading').show(); - - $jobTypes.filter(':checked').each(function () { - var $this = $(this); - $('#trJobSubType' + $this.val()).find('input[type="checkbox"]:checked').each(function () { - data.SubTypes.push($(this).val()); - }); - }); - - $.ajax({ - url: '@Url.Action(MVC.API.DocumentTemplate.UpdateSubTypes(Model.DocumentTemplate.Id))', - dataType: 'json', - type: 'POST', - traditional: true, - data: data, - success: function (d) { - if (d == 'OK') { - $ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow'); - scopeChange(); - } else { - $ajaxLoading.hide(); - alert('Unable to update job types: ' + d); - } - }, - error: function (jqXHR, textStatus, errorThrown) { - alert('Unable to update job types: ' + textStatus); - $ajaxLoading.hide(); - } - }); - return false; - }); - - scopeChange(); }); } else { - @Model.DocumentTemplate.Scope +
    @Model.DocumentTemplate.Scope
    + } + @if (canConfig || (Model.DocumentTemplate.Scope == DocumentTemplate.DocumentTemplateScopes.Job)) + { +
    +

    Filter:

    +
    + @if (Model.DocumentTemplate.JobSubTypes.Count > 0) + { +
      + @foreach (var jobType in Model.DocumentTemplate.JobSubTypes.GroupBy(jst => jst.JobType).OrderBy(jtg => jtg.Key.Description)) + { +
    • + @jobType.Key.Description +
        + @if (jobType.Count() == Model.JobTypes.FirstOrDefault(jt => jt.Id == jobType.Key.Id).JobSubTypes.Count) + { +
      • [All Sub Types]
      • + } + else + { + foreach (var jobSubType in jobType) + { +
      • @jobSubType.Description
      • + } + } +
      +
    • + } +
    + } + else + { + <No Filter> + } +
    + @if (canConfig) + { + Update +
    + @using (Html.BeginForm(MVC.API.DocumentTemplate.UpdateJobSubTypes(Model.DocumentTemplate.Id, null, true))) + { + var selectedTypes = Model.DocumentTemplate.JobSubTypes.Select(jst => jst.JobType).Distinct().ToList(); + foreach (var jt in Model.JobTypes) + { +
    +

    +

    +
    + @CommonHelpers.CheckboxBulkSelect(string.Format("CheckboxBulkSelect_{0}", jt.Id), "div") + @CommonHelpers.CheckBoxList("JobSubTypes", jt.JobSubTypes.OrderBy(jst => jst.Description).ToSelectListItems(Model.DocumentTemplate.JobSubTypes), 2) +
    +
    + } + } +
    + + } +
    } - @if (canConfig || (Model.DocumentTemplate.Scope == DocumentTemplate.DocumentTemplateScopes.Job)) - { - - Types: - - - @CommonHelpers.CheckBoxList("Types", Model.JobTypes.ToSelectListItems(Model.Types), 2) - - - foreach (var jt in Model.JobTypes) - { - - - @jt.Description
    - Sub Types
    - @if (canConfig) - { - @CommonHelpers.CheckboxBulkSelect(string.Format("CheckboxBulkSelect_{0}", jt.Id)) - } - - - @CommonHelpers.CheckBoxList("SubTypes", Model.JobSubTypes.Where(jst => jst.JobTypeId == jt.Id).ToList().ToSelectListItems(Model.SubTypes), 2) - - - } - if (canConfig) - { - - - - Save Job Types@AjaxHelpers.AjaxLoader() - - - } - else if (Model.DocumentTemplate.Scope == DocumentTemplate.DocumentTemplateScopes.Job) - { - - } - } Template PDF diff --git a/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.generated.cs b/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.generated.cs index 179f208c..0342619c 100644 --- a/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.generated.cs +++ b/Disco.Web/Areas/Config/Views/DocumentTemplate/Show.generated.cs @@ -29,6 +29,7 @@ namespace Disco.Web.Areas.Config.Views.DocumentTemplate using Disco; using Disco.BI.Extensions; using Disco.Models.Repository; + using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Web; using Disco.Web; @@ -421,60 +422,10 @@ WriteLiteral(@"> Write(Url.Action(MVC.API.DocumentTemplate.UpdateScope(Model.DocumentTemplate.Id))); - #line default - #line hidden -WriteLiteral("\',\r\n dataType: \'json\',\r\n " + -" data: data,\r\n success: function (d) {\r\n " + -" if (d == \'OK\') {\r\n " + -" $ajaxLoading.hide().next(\'.ajaxOk\').show().delay(\'fast\').fadeOut(\'slow" + -"\');\r\n scopeChange();\r\n " + -" } else {\r\n $ajaxLoading." + -"hide();\r\n alert(\'Unable to update scope: " + -"\' + d);\r\n }\r\n " + -"},\r\n error: function (jqXHR, textStatus, errorThr" + -"own) {\r\n alert(\'Unable to update scope: \' + t" + -"extStatus);\r\n $ajaxLoading.hide();\r\n " + -" }\r\n });\r\n " + -" });\r\n\r\n var $trJobTypes = $(\'#trJobTypes\');\r\n " + -" var $trJobTypeActions = $(\'#trJobTypeActions\');\r\n " + -" var $jobTypes = $trJobTypes.find(\'input[type=\"checkbox\"]\');\r\n " + -" $jobTypes.change(jobTypesChange);\r\n\r\n functi" + -"on scopeChange() {\r\n if ($scope.val() == \'Job\') {\r\n " + -" $trJobTypes.show();\r\n " + -" $trJobTypeActions.show();\r\n jobTypesChange();\r" + -"\n } else {\r\n $trJobTyp" + -"es.hide();\r\n $trJobTypeActions.hide();\r\n " + -" $jobTypes.filter(\':checked\').each(function () {\r\n " + -" $(this).prop(\'checked\', false);\r\n " + -" });\r\n $(\'.jobSubTypes\').hide().find(" + -"\'input[type=\"checkbox\"]:checked\').each(function () {\r\n " + -" $(this).prop(\'checked\', false);\r\n });\r\n" + -" }\r\n }\r\n\r\n " + -" function jobTypesChange() {\r\n $(\'.jobSubTypes\').h" + -"ide();\r\n $jobTypes.filter(\':checked\').each(function (" + -") {\r\n $(\'#trJobSubType\' + $(this).val()).show();\r" + -"\n });\r\n }\r\n\r\n " + -" $(\'#TypeAction_Save\').click(function () {\r\n va" + -"r data = { SubTypes: [] };\r\n var $ajaxLoading = $(\'#T" + -"ypeAction_Save\').next(\'.ajaxLoading\').show();\r\n\r\n $jo" + -"bTypes.filter(\':checked\').each(function () {\r\n va" + -"r $this = $(this);\r\n $(\'#trJobSubType\' + $this.va" + -"l()).find(\'input[type=\"checkbox\"]:checked\').each(function () {\r\n " + -" data.SubTypes.push($(this).val());\r\n " + -" });\r\n });\r\n\r\n $.aj" + -"ax({\r\n url: \'"); - - - #line 210 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - Write(Url.Action(MVC.API.DocumentTemplate.UpdateSubTypes(Model.DocumentTemplate.Id))); - - #line default #line hidden WriteLiteral(@"', dataType: 'json', - type: 'POST', - traditional: true, data: data, success: function (d) { if (d == 'OK') { @@ -482,247 +433,440 @@ WriteLiteral(@"', scopeChange(); } else { $ajaxLoading.hide(); - alert('Unable to update job types: ' + d); + alert('Unable to update scope: ' + d); } }, error: function (jqXHR, textStatus, errorThrown) { - alert('Unable to update job types: ' + textStatus); + alert('Unable to update scope: ' + textStatus); $ajaxLoading.hide(); } }); - return false; }); - scopeChange(); + var $JobSubTypes = $('#Config_DocumentTemplates_JobSubTypes'); + + function scopeChange() { + if ($scope.val() == 'Job') { + $JobSubTypes.slideDown('fast'); + } else { + $JobSubTypes.slideUp('fast'); + } + } }); "); - #line 235 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 180 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" } else { - - - #line default - #line hidden - - #line 238 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - Write(Model.DocumentTemplate.Scope); #line default #line hidden +WriteLiteral("
    "); + - #line 238 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - + #line 183 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + Write(Model.DocumentTemplate.Scope); + + + #line default + #line hidden +WriteLiteral("
    \r\n"); + + + #line 184 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" } #line default #line hidden -WriteLiteral(" \r\n \r\n"); +WriteLiteral(" "); - #line 242 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - - - #line default - #line hidden - - #line 242 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - if (canConfig || (Model.DocumentTemplate.Scope == DocumentTemplate.DocumentTemplateScopes.Job)) - { + #line 185 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + if (canConfig || (Model.DocumentTemplate.Scope == DocumentTemplate.DocumentTemplateScopes.Job)) + { #line default #line hidden -WriteLiteral(" \r\n Types:\r\n \r\n \r\n"); - -WriteLiteral(" "); +WriteLiteral(" "); - #line 248 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - Write(CommonHelpers.CheckBoxList("Types", Model.JobTypes.ToSelectListItems(Model.Types), 2)); + #line 187 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + Write(Model.DocumentTemplate.Scope != DocumentTemplate.DocumentTemplateScopes.Job ? "style=\"display: none;\" " : null); #line default #line hidden -WriteLiteral("\r\n \r\n \r\n"); +WriteLiteral(">\r\n

    Filter:

    \r\n
    \r\n"); - #line 251 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - foreach (var jt in Model.JobTypes) - { - - - #line default - #line hidden -WriteLiteral(" (jt.Id - - #line default - #line hidden -, 12505), false) -); - -WriteLiteral(" class=\"jobSubTypes\""); - -WriteLiteral(">\r\n \r\n"); - -WriteLiteral(" "); - - - #line 255 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - Write(jt.Description); - - - #line default - #line hidden -WriteLiteral("
    \r\n Sub Types
    \r\n"); - - - #line 257 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - + #line 190 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line default #line hidden - #line 257 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - if (canConfig) - { + #line 190 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + if (Model.DocumentTemplate.JobSubTypes.Count > 0) + { + + + #line default + #line hidden +WriteLiteral("
      \r\n"); + + + #line 193 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + + + #line default + #line hidden + + #line 193 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + foreach (var jobType in Model.DocumentTemplate.JobSubTypes.GroupBy(jst => jst.JobType).OrderBy(jtg => jtg.Key.Description)) + { + + + #line default + #line hidden +WriteLiteral("
    • \r\n"); + +WriteLiteral(" "); + + + #line 196 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + Write(jobType.Key.Description); + + + #line default + #line hidden +WriteLiteral("\r\n
        \r\n"); + + + #line 198 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + + + #line default + #line hidden + + #line 198 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + if (jobType.Count() == Model.JobTypes.FirstOrDefault(jt => jt.Id == jobType.Key.Id).JobSubTypes.Count) + { + + + #line default + #line hidden +WriteLiteral("
      • [All Sub Types]
      • \r\n"); + + + #line 201 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + } + else + { + foreach (var jobSubType in jobType) + { + + + #line default + #line hidden +WriteLiteral("
      • "); + + + #line 206 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + Write(jobSubType.Description); + + + #line default + #line hidden +WriteLiteral("
      • \r\n"); + + + #line 207 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + } + } + + + #line default + #line hidden +WriteLiteral("
      \r\n " + +"
    • \r\n"); + + + #line 211 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
    \r\n"); + + + #line 213 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral(" <No Filter>\r\n"); + + + #line 217 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
    \r\n"); + + + #line 219 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" #line default #line hidden - #line 259 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - Write(CommonHelpers.CheckboxBulkSelect(string.Format("CheckboxBulkSelect_{0}", jt.Id))); + #line 219 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + if (canConfig) + { #line default #line hidden - - #line 259 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" - - } +WriteLiteral("
    \r\n"); - #line 376 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 394 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" } else { @@ -950,7 +1094,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 380 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 398 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" Write(Model.DocumentTemplate.FilterExpression); @@ -959,7 +1103,7 @@ WriteLiteral(" "); WriteLiteral("\r\n \r\n"); - #line 382 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 400 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" } } @@ -970,7 +1114,7 @@ WriteLiteral(" \r\n \r\n \r\n\r\n\r\n"); - #line 389 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 407 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" Write(Html.Partial(MVC.Config.DocumentTemplate.Views._ExpressionsTable, Model.TemplateExpressions)); @@ -1032,13 +1176,13 @@ WriteLiteral(" class=\"actionBar\""); WriteLiteral(">\r\n"); - #line 428 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 446 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" #line default #line hidden - #line 428 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 446 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" if (Authorization.Has(Claims.Config.Show)) { @@ -1046,14 +1190,14 @@ WriteLiteral(">\r\n"); #line default #line hidden - #line 430 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 448 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" Write(Html.ActionLinkButton("Expression Browser", MVC.Config.DocumentTemplate.ExpressionBrowser())); #line default #line hidden - #line 430 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 448 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" } @@ -1063,7 +1207,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 432 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 450 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" if (canBulkGenerate) { @@ -1086,16 +1230,16 @@ WriteLiteral(" id=\"dialogBulkGenerate\""); WriteLiteral(" class=\"hiddenDialog\""); -WriteAttribute("title", Tuple.Create(" title=\"", 20927), Tuple.Create("\"", 20978) -, Tuple.Create(Tuple.Create("", 20935), Tuple.Create("Bulk", 20935), true) -, Tuple.Create(Tuple.Create(" ", 20939), Tuple.Create("Generate:", 20940), true) +WriteAttribute("title", Tuple.Create(" title=\"", 23181), Tuple.Create("\"", 23232) +, Tuple.Create(Tuple.Create("", 23189), Tuple.Create("Bulk", 23189), true) +, Tuple.Create(Tuple.Create(" ", 23193), Tuple.Create("Generate:", 23194), true) - #line 435 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" -, Tuple.Create(Tuple.Create(" ", 20949), Tuple.Create(Model.DocumentTemplate.Id + #line 453 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" +, Tuple.Create(Tuple.Create(" ", 23203), Tuple.Create(Model.DocumentTemplate.Id #line default #line hidden -, 20950), false) +, 23204), false) ); WriteLiteral(">\r\n \r\n \r\n \r\n"); - #line 447 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 465 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" #line default #line hidden - #line 447 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 465 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerate(Model.DocumentTemplate.Id), FormMethod.Post)) { @@ -1162,7 +1306,7 @@ WriteLiteral(" data-val-required=\"Identifiers are required\""); WriteLiteral(">\r\n"); - #line 451 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 469 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" } @@ -1171,7 +1315,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" \r\n"); - #line 453 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 471 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" @@ -1211,7 +1355,7 @@ WriteLiteral(" \r\n"); - #line 505 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" + #line 523 "..\..\Areas\Config\Views\DocumentTemplate\Show.cshtml" } @@ -1220,7 +1364,7 @@ WriteLiteral(" +} \ No newline at end of file diff --git a/Disco.Web/Areas/Config/Views/JobQueue/Create.generated.cs b/Disco.Web/Areas/Config/Views/JobQueue/Create.generated.cs new file mode 100644 index 00000000..75fad008 --- /dev/null +++ b/Disco.Web/Areas/Config/Views/JobQueue/Create.generated.cs @@ -0,0 +1,186 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34003 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Disco.Web.Areas.Config.Views.JobQueue +{ + 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.BI.Extensions; + using Disco.Models.Repository; + 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("~/Areas/Config/Views/JobQueue/Create.cshtml")] + public partial class Create : Disco.Services.Web.WebViewPage + { + public Create() + { + } + public override void Execute() + { + + #line 2 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" + + Authorization.RequireAll(Claims.Config.JobQueue.Create, Claims.Config.JobQueue.Configure); + ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Job Queues", MVC.Config.JobQueue.Index(null), "Create"); + + + #line default + #line hidden +WriteLiteral("\r\n"); + + + #line 6 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" + using (Html.BeginForm()) +{ + + + #line default + #line hidden + + #line 8 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" +Write(Html.HiddenFor(m => m.JobQueue.Icon)); + + + #line default + #line hidden + + #line 8 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" + + + + #line default + #line hidden + + #line 9 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" +Write(Html.HiddenFor(m => m.JobQueue.IconColour)); + + + #line default + #line hidden + + #line 9 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" + + + + #line default + #line hidden + + #line 10 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" +Write(Html.HiddenFor(m => m.JobQueue.Priority)); + + + #line default + #line hidden + + #line 10 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" + + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n Description:\r\n \r\n \r\n \r\n
    \r\n N" + +"ame:\r\n \r\n"); + +WriteLiteral(" "); + + + #line 18 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" + Write(Html.EditorFor(model => model.JobQueue.Name)); + + + #line default + #line hidden +WriteLiteral("
    "); + + + #line 18 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" + Write(Html.ValidationMessageFor(model => model.JobQueue.Name)); + + + #line default + #line hidden +WriteLiteral("\r\n
    " + +"\r\n"); + +WriteLiteral(" "); + + + #line 26 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" + Write(Html.EditorFor(model => model.JobQueue.Description)); + + + #line default + #line hidden +WriteLiteral("
    "); + + + #line 26 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" + Write(Html.ValidationMessageFor(model => model.JobQueue.Description)); + + + #line default + #line hidden +WriteLiteral("\r\n
    \r\n \r\n \r\n

    \r\n \r\n"); + +WriteLiteral(" \r\n $(function () {\r\n $(\'#JobQueue_Name\').focus().select();\r\n " + +" });\r\n \r\n"); + + + #line 39 "..\..\Areas\Config\Views\JobQueue\Create.cshtml" +} + + #line default + #line hidden + } + } +} +#pragma warning restore 1591 diff --git a/Disco.Web/Areas/Config/Views/JobQueue/Index.cshtml b/Disco.Web/Areas/Config/Views/JobQueue/Index.cshtml new file mode 100644 index 00000000..fd994b13 --- /dev/null +++ b/Disco.Web/Areas/Config/Views/JobQueue/Index.cshtml @@ -0,0 +1,50 @@ +@model Disco.Web.Areas.Config.Models.JobQueue.IndexModel +@{ + Authorization.RequireAll(Claims.Config.JobQueue.Create, Claims.Config.JobQueue.Configure); + ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Job Queues", MVC.Config.JobQueue.Index(null)); +} +
    + @if (Model.Tokens.Count == 0) + { +
    +

    No job queues are configured

    +
    + } + else + { + + + + + + + @foreach (var item in Model.Tokens) + { + + + + + + } +
    NamePriorityLinked Groups/Users
    + + + @item.JobQueue.Name + + + + + @if (item.SubjectIds.Count == 0) + { + <None> + } + else + { + @(string.Join(", ", item.SubjectIds.OrderBy(i => i))) + } +
    + } +
    + @Html.ActionLinkButton("Create Job Queue", MVC.Config.JobQueue.Create()) +
    +
    diff --git a/Disco.Web/Areas/Config/Views/JobQueue/Index.generated.cs b/Disco.Web/Areas/Config/Views/JobQueue/Index.generated.cs new file mode 100644 index 00000000..7ed833bd --- /dev/null +++ b/Disco.Web/Areas/Config/Views/JobQueue/Index.generated.cs @@ -0,0 +1,269 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34003 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Disco.Web.Areas.Config.Views.JobQueue +{ + 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.BI.Extensions; + using Disco.Models.Repository; + 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("~/Areas/Config/Views/JobQueue/Index.cshtml")] + public partial class Index : Disco.Services.Web.WebViewPage + { + public Index() + { + } + public override void Execute() + { + + #line 2 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + + Authorization.RequireAll(Claims.Config.JobQueue.Create, Claims.Config.JobQueue.Configure); + ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Job Queues", MVC.Config.JobQueue.Index(null)); + + + #line default + #line hidden +WriteLiteral("\r\n\r\n"); + + + #line 7 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + + + #line default + #line hidden + + #line 7 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + if (Model.Tokens.Count == 0) + { + + + #line default + #line hidden +WriteLiteral(" \r\n

    No job queues are configured

    \r\n \r\n"); + + + #line 12 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n Name\r\n Priority<" + +"/th>\r\n Linked Groups/Users\r\n \r\n"); + + + #line 21 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + + + #line default + #line hidden + + #line 21 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + foreach (var item in Model.Tokens) + { + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n (Url.Action(MVC.Config.JobQueue.Index(item.JobQueue.Id)) + + #line default + #line hidden +, 859), false) +); + +WriteLiteral(">\r\n (item.JobQueue.Icon + + #line default + #line hidden +, 963), false) +, Tuple.Create(Tuple.Create(" ", 984), Tuple.Create("fa-lg", 985), true) +, Tuple.Create(Tuple.Create(" ", 990), Tuple.Create("d-", 991), true) + + #line 26 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" +, Tuple.Create(Tuple.Create("", 993), Tuple.Create(item.JobQueue.IconColour + + #line default + #line hidden +, 993), false) +); + +WriteLiteral(">\r\n"); + +WriteLiteral(" "); + + + #line 27 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + Write(item.JobQueue.Name); + + + #line default + #line hidden +WriteLiteral("\r\n \r\n \r\n \r\n (item.JobQueue.Priority.ToString().ToLower() + + #line default + #line hidden +, 1208), false) +); + +WriteAttribute("title", Tuple.Create(" title=\"", 1255), Tuple.Create("\"", 1308) + + #line 31 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + , Tuple.Create(Tuple.Create("", 1263), Tuple.Create(item.JobQueue.Priority.ToString() + + #line default + #line hidden +, 1263), false) +, Tuple.Create(Tuple.Create(" ", 1299), Tuple.Create("Priority", 1300), true) +); + +WriteLiteral(">\r\n \r\n \r\n"); + + + #line 34 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + + + #line default + #line hidden + + #line 34 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + if (item.SubjectIds.Count == 0) + { + + + #line default + #line hidden +WriteLiteral(" <None>\r\n"); + + + #line 37 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + } + else + { + + + #line default + #line hidden + + #line 40 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + Write(string.Join(", ", item.SubjectIds.OrderBy(i => i))); + + + #line default + #line hidden + + #line 40 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + + } + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n"); + + + #line 44 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + } + + + #line default + #line hidden +WriteLiteral(" \r\n"); + + + #line 46 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + } + + + #line default + #line hidden +WriteLiteral(" \r\n"); + +WriteLiteral(" "); + + + #line 48 "..\..\Areas\Config\Views\JobQueue\Index.cshtml" + Write(Html.ActionLinkButton("Create Job Queue", MVC.Config.JobQueue.Create())); + + + #line default + #line hidden +WriteLiteral("\r\n \r\n\r\n"); + + } + } +} +#pragma warning restore 1591 diff --git a/Disco.Web/Areas/Config/Views/JobQueue/Show.cshtml b/Disco.Web/Areas/Config/Views/JobQueue/Show.cshtml new file mode 100644 index 00000000..12e500a8 --- /dev/null +++ b/Disco.Web/Areas/Config/Views/JobQueue/Show.cshtml @@ -0,0 +1,657 @@ +@model Disco.Web.Areas.Config.Models.JobQueue.ShowModel +@using Disco.Services.Jobs.JobQueues; +@{ + Authorization.Require(Claims.Config.JobQueue.Show); + + ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Job Queues", MVC.Config.JobQueue.Index(null), Model.Token.JobQueue.ToString()); + + var canConfig = Authorization.Has(Claims.Config.JobQueue.Configure); + var canDelete = (Authorization.Has(Claims.Config.JobQueue.Delete) && Model.CanDelete); + + Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers"); +} +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Id: + + @Html.DisplayFor(model => model.Token.JobQueue.Id) +
    Name: + @if (canConfig) + {@Html.EditorFor(model => model.Token.JobQueue.Name) + @AjaxHelpers.AjaxSave() + @AjaxHelpers.AjaxLoader() + + } + else + { + @Model.Token.JobQueue.Name + } +
    Description: + @if (canConfig) + {@Html.EditorFor(model => model.Token.JobQueue.Description) + @AjaxHelpers.AjaxSave() + @AjaxHelpers.AjaxLoader() + + } + else + { +
    +                        @Model.Token.JobQueue.Description
    +                    
    + } +
    Statistics: + +
    @Model.OpenJobCount job@(Model.OpenJobCount != 1 ? "s" : null) open
    +
    @Model.TotalJobCount total job@(Model.TotalJobCount != 1 ? "s" : null)
    +
    Icon: + + + @if (canConfig) + { +
    + Update +
    +
    +
    + @foreach (var icon in JobQueueService.Icons) + { + + } +
    +
    + @foreach (var colour in JobQueueService.IconColours) + { + + } +
    +
    +
    + +
    + } +
    Priority: + @if (canConfig) + { + var priorityValue = Model.Token.JobQueue.Priority.ToString(); + var priorityItems = Enum.GetNames(typeof(JobQueuePriority)).Select(i => new SelectListItem() { Text = i, Value = i, Selected = (i == priorityValue) }).ToList(); + + @Html.DropDownListFor(m => m.Token.JobQueue.Priority, priorityItems) + @AjaxHelpers.AjaxSave() + @AjaxHelpers.AjaxLoader() + + } + else + { + @Model.Token.JobQueue.Priority.ToString() + } +
    Default SLA: + @if (canConfig) + { + var slaOptions = JobQueueService.SlaOptions.Select(o => new SelectListItem() { Text = o.Value, Value = o.Key.ToString() }).ToList(); + + if (this.Model.Token.JobQueue.DefaultSLAExpiry.HasValue) + { + var slaValue = this.Model.Token.JobQueue.DefaultSLAExpiry.Value; + if (JobQueueService.SlaOptions.Where(o => o.Key == slaValue).Count() == 0) + { + string slaValueText; + if (slaValue % (60 * 24 * 7 * 4) == 0) + { slaValueText = string.Format("{0} months", slaValue / (60 * 24 * 7 * 4)); } + else if (slaValue % (60 * 24 * 7) == 0) + { slaValueText = string.Format("{0} weeks", slaValue / (60 * 24 * 7)); } + else if (slaValue % (60 * 24) == 0) + { slaValueText = string.Format("{0} days", slaValue / (60 * 24)); } + else if (slaValue % (60) == 0) + { slaValueText = string.Format("{0} hours", slaValue / 60); } + else + { slaValueText = string.Format("{0} minutes", slaValue); } + + slaOptions.Insert(0, new SelectListItem() { Text = string.Format("{0} ", slaValueText), Value = slaValue.ToString() }); + } + } + @Html.DropDownListFor(m => m.Token.JobQueue.DefaultSLAExpiry, slaOptions) + @AjaxHelpers.AjaxSave() + @AjaxHelpers.AjaxLoader() + + } + else + { + if (this.Model.Token.JobQueue.DefaultSLAExpiry.HasValue) + { + var slaValue = this.Model.Token.JobQueue.DefaultSLAExpiry.Value; + var slaOption = JobQueueService.SlaOptions.Where(o => o.Key == slaValue).ToArray(); + if (slaOption.Length > 0) + { + @slaOption[0].Value + } + else + { + <None> + } + } + else + { + <None> + } + } +
    Member Groups/Users: + @if (Model.Token.SubjectIds.Count == 0) + { + None Associated + } + else + { +
      + @foreach (var sg in Model.Subjects) + { + var displayName = sg.Id == sg.Name ? sg.Id : string.Format("{0} [{1}]", sg.Name, sg.Id); +
    • @if (sg.IsGroup) + { + @displayName + } + else + { + @displayName + }
    • + } +
    + } + @if (canConfig) + { +
    + Update +
    +
    + None Associated +
      + @foreach (var sg in Model.Subjects) + { + var displayName = sg.Id == sg.Name ? sg.Id : string.Format("{0} [{1}]", sg.Name, sg.Id); +
    • @if (sg.IsGroup) + { + @displayName + } + else + { + @displayName + }
    • + } +
    +
    +
    + + Add +
    +
    +
    + +
    + } +
    Automatically Add Jobs: +
    + @if (Model.Token.JobQueue.JobSubTypes.Count > 0) + { +
      + @foreach (var jobType in Model.Token.JobQueue.JobSubTypes.GroupBy(jst => jst.JobType).OrderBy(jtg => jtg.Key.Description)) + { +
    • + @jobType.Key.Description +
        + @if (jobType.Count() == Model.JobTypes.FirstOrDefault(jt => jt.Id == jobType.Key.Id).JobSubTypes.Count) + { +
      • [All Sub Types]
      • + } + else + { + foreach (var jobSubType in jobType) + { +
      • @jobSubType.Description
      • + } + } +
      +
    • + } +
    + } + else + { + <None> + } +
    + @if (canConfig) + { + Update +
    + @using (Html.BeginForm(MVC.API.JobQueue.UpdateJobSubTypes(Model.Token.JobQueue.Id, null, true))) + { + var selectedTypes = Model.Token.JobQueue.JobSubTypes.Select(jst => jst.JobType).Distinct().ToList(); + foreach (var jt in Model.JobTypes) + { +
    +

    +

    +
    + @CommonHelpers.CheckboxBulkSelect(string.Format("CheckboxBulkSelect_{0}", jt.Id), "div") + @CommonHelpers.CheckBoxList("JobSubTypes", jt.JobSubTypes.OrderBy(jst => jst.Description).ToSelectListItems(Model.Token.JobQueue.JobSubTypes), 2) +
    +
    + } + } +
    + + } +
    +  When jobs of these types are created, they will automatically be added into this queue. +
    +
    +
    +@if (canDelete) +{ +
    + @Html.ActionLinkButton("Delete", MVC.API.JobQueue.Delete(Model.Token.JobQueue.Id, true), "Config_JobQueues_Actions_Delete_Button") +
    +

    + + This item will be permanently deleted and cannot be recovered.
    +
    + Are you sure? +

    +
    + +
    +} \ No newline at end of file diff --git a/Disco.Web/Areas/Config/Views/JobQueue/Show.generated.cs b/Disco.Web/Areas/Config/Views/JobQueue/Show.generated.cs new file mode 100644 index 00000000..369ce047 --- /dev/null +++ b/Disco.Web/Areas/Config/Views/JobQueue/Show.generated.cs @@ -0,0 +1,1839 @@ +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34003 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Disco.Web.Areas.Config.Views.JobQueue +{ + 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.BI.Extensions; + using Disco.Models.Repository; + using Disco.Services; + using Disco.Services.Authorization; + + #line 2 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + using Disco.Services.Jobs.JobQueues; + + #line default + #line hidden + using Disco.Services.Web; + using Disco.Web; + using Disco.Web.Extensions; + + [System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")] + [System.Web.WebPages.PageVirtualPathAttribute("~/Areas/Config/Views/JobQueue/Show.cshtml")] + public partial class Show : Disco.Services.Web.WebViewPage + { + public Show() + { + } + public override void Execute() + { + + #line 3 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + Authorization.Require(Claims.Config.JobQueue.Show); + + ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Job Queues", MVC.Config.JobQueue.Index(null), Model.Token.JobQueue.ToString()); + + var canConfig = Authorization.Has(Claims.Config.JobQueue.Configure); + var canDelete = (Authorization.Has(Claims.Config.JobQueue.Delete) && Model.CanDelete); + + Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers"); + + + #line default + #line hidden +WriteLiteral("\r\n\r\n \r\n \r\n Id:\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n " + +"
    \r\n"); + +WriteLiteral(" "); + + + #line 19 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Html.DisplayFor(model => model.Token.JobQueue.Id)); + + + #line default + #line hidden +WriteLiteral("\r\n
    Name:\r\n " + +" "); + + + #line 25 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (canConfig) + { + + #line default + #line hidden + + #line 26 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Html.EditorFor(model => model.Token.JobQueue.Name)); + + + #line default + #line hidden + + #line 26 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden + + #line 27 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(AjaxHelpers.AjaxSave()); + + + #line default + #line hidden + + #line 27 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden + + #line 28 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); + + + #line default + #line hidden + + #line 28 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden +WriteLiteral(" \r\n $(function () {\r\n document.DiscoFun" + +"ctions.PropertyChangeHelper(\r\n $(\'#Token_JobQueue_Nam" + +"e\'),\r\n \'Invalid Name\',\r\n \'" + +""); + + + #line 34 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Url.Action(MVC.API.JobQueue.UpdateName(Model.Token.JobQueue.Id))); + + + #line default + #line hidden +WriteLiteral("\',\r\n \'QueueName\'\r\n );\r\n " + +" });\r\n \r\n"); + + + #line 39 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + else + { + + + #line default + #line hidden + + #line 42 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Model.Token.JobQueue.Name); + + + #line default + #line hidden + + #line 42 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + } + + + #line default + #line hidden +WriteLiteral("
    Description:\r\n " + +" "); + + + #line 49 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (canConfig) + { + + #line default + #line hidden + + #line 50 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Html.EditorFor(model => model.Token.JobQueue.Description)); + + + #line default + #line hidden + + #line 50 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden + + #line 51 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(AjaxHelpers.AjaxSave()); + + + #line default + #line hidden + + #line 51 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden + + #line 52 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); + + + #line default + #line hidden + + #line 52 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden +WriteLiteral(" \r\n $(function () {\r\n document.DiscoFun" + +"ctions.PropertyChangeHelper(\r\n $(\'#Token_JobQueue_Des" + +"cription\'),\r\n \'Invalid Description\',\r\n " + +" \'"); + + + #line 58 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Url.Action(MVC.API.JobQueue.UpdateDescription(Model.Token.JobQueue.Id))); + + + #line default + #line hidden +WriteLiteral("\',\r\n \'Description\'\r\n );\r\n " + +" });\r\n \r\n"); + + + #line 63 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral("
    \r\n");
    +
    +WriteLiteral("                        ");
    +
    +            
    +            #line 67 "..\..\Areas\Config\Views\JobQueue\Show.cshtml"
    +                   Write(Model.Token.JobQueue.Description);
    +
    +            
    +            #line default
    +            #line hidden
    +WriteLiteral("\r\n                    
    \r\n"); + + + #line 69 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
    Statistics:\r\n " + +" \r\n
    "); + + + #line 76 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Model.OpenJobCount); + + + #line default + #line hidden +WriteLiteral(" job"); + + + #line 76 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Model.OpenJobCount != 1 ? "s" : null); + + + #line default + #line hidden +WriteLiteral(" open
    \r\n
    "); + + + #line 77 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Model.TotalJobCount); + + + #line default + #line hidden +WriteLiteral(" total job"); + + + #line 77 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Model.TotalJobCount != 1 ? "s" : null); + + + #line default + #line hidden +WriteLiteral("
    \r\n
    Icon:\r\n " + +" \r\n
    Priority:\r\n " + +" "); + + + #line 189 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (canConfig) + { + var priorityValue = Model.Token.JobQueue.Priority.ToString(); + var priorityItems = Enum.GetNames(typeof(JobQueuePriority)).Select(i => new SelectListItem() { Text = i, Value = i, Selected = (i == priorityValue) }).ToList(); + + + #line default + #line hidden +WriteLiteral(" (priorityValue.ToLower() + + #line default + #line hidden +, 9129), false) +); + +WriteAttribute("title", Tuple.Create(" title=\"", 9156), Tuple.Create("\"", 9189) + + #line 193 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" +, Tuple.Create(Tuple.Create("", 9164), Tuple.Create(priorityValue + + #line default + #line hidden +, 9164), false) +, Tuple.Create(Tuple.Create(" ", 9180), Tuple.Create("Priority", 9181), true) +); + +WriteLiteral(">\r\n"); + + + #line 194 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 194 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Html.DropDownListFor(m => m.Token.JobQueue.Priority, priorityItems)); + + + #line default + #line hidden + + #line 194 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden + + #line 195 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(AjaxHelpers.AjaxSave()); + + + #line default + #line hidden + + #line 195 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden + + #line 196 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); + + + #line default + #line hidden + + #line 196 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden +WriteLiteral(" + $(function () { + var element = $('#Token_JobQueue_Priority'); + + document.DiscoFunctions.PropertyChangeHelper( + element, + 'Invalid Priority', + '"); + + + #line 204 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Url.Action(MVC.API.JobQueue.UpdatePriority(Model.Token.JobQueue.Id))); + + + #line default + #line hidden +WriteLiteral(@"', + 'Priority' + ); + + element.change(function () { + var icon = element.closest('td').find('i').first(); + icon[0].className = ''; + icon.addClass('fa d-priority-' + element.val().toLowerCase()).attr('title', element.val() + ' Priority'); + }); + }); + +"); + + + #line 215 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + else + { + + + #line default + #line hidden + + #line 218 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Model.Token.JobQueue.Priority.ToString()); + + + #line default + #line hidden + + #line 218 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + } + + + #line default + #line hidden +WriteLiteral("
    Default SLA:\r\n " + +" "); + + + #line 225 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (canConfig) + { + var slaOptions = JobQueueService.SlaOptions.Select(o => new SelectListItem() { Text = o.Value, Value = o.Key.ToString() }).ToList(); + + if (this.Model.Token.JobQueue.DefaultSLAExpiry.HasValue) + { + var slaValue = this.Model.Token.JobQueue.DefaultSLAExpiry.Value; + if (JobQueueService.SlaOptions.Where(o => o.Key == slaValue).Count() == 0) + { + string slaValueText; + if (slaValue % (60 * 24 * 7 * 4) == 0) + { slaValueText = string.Format("{0} months", slaValue / (60 * 24 * 7 * 4)); } + else if (slaValue % (60 * 24 * 7) == 0) + { slaValueText = string.Format("{0} weeks", slaValue / (60 * 24 * 7)); } + else if (slaValue % (60 * 24) == 0) + { slaValueText = string.Format("{0} days", slaValue / (60 * 24)); } + else if (slaValue % (60) == 0) + { slaValueText = string.Format("{0} hours", slaValue / 60); } + else + { slaValueText = string.Format("{0} minutes", slaValue); } + + slaOptions.Insert(0, new SelectListItem() { Text = string.Format("{0} ", slaValueText), Value = slaValue.ToString() }); + } + } + + + #line default + #line hidden + + #line 249 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Html.DropDownListFor(m => m.Token.JobQueue.DefaultSLAExpiry, slaOptions)); + + + #line default + #line hidden + + #line 249 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden + + #line 250 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(AjaxHelpers.AjaxSave()); + + + #line default + #line hidden + + #line 250 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden + + #line 251 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); + + + #line default + #line hidden + + #line 251 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + + #line default + #line hidden +WriteLiteral(" + $(function () { + document.DiscoFunctions.PropertyChangeHelper( + $('#Token_JobQueue_DefaultSLAExpiry'), + 'Invalid Default SLA', + '"); + + + #line 257 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Url.Action(MVC.API.JobQueue.UpdateDefaultSLAExpiry(Model.Token.JobQueue.Id))); + + + #line default + #line hidden +WriteLiteral("\',\r\n \'DefaultSLAExpiry\'\r\n );\r\n " + +" });\r\n \r\n"); + + + #line 262 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + else + { + if (this.Model.Token.JobQueue.DefaultSLAExpiry.HasValue) + { + var slaValue = this.Model.Token.JobQueue.DefaultSLAExpiry.Value; + var slaOption = JobQueueService.SlaOptions.Where(o => o.Key == slaValue).ToArray(); + if (slaOption.Length > 0) + { + + + #line default + #line hidden + + #line 271 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(slaOption[0].Value); + + + #line default + #line hidden + + #line 271 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + } + else + { + + + #line default + #line hidden +WriteLiteral(" "); + +WriteLiteral("<None>"); + +WriteLiteral("\r\n"); + + + #line 276 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + } + else + { + + + #line default + #line hidden +WriteLiteral(" "); + +WriteLiteral("<None>"); + +WriteLiteral("\r\n"); + + + #line 281 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + } + + + #line default + #line hidden +WriteLiteral("
    Member Groups/Use" + +"rs:\r\n"); + + + #line 288 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 288 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (Model.Token.SubjectIds.Count == 0) + { + + + #line default + #line hidden +WriteLiteral(" None Associated\r\n"); + + + #line 291 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral(" \r\n"); + + + #line 295 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 295 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + foreach (var sg in Model.Subjects) + { + var displayName = sg.Id == sg.Name ? sg.Id : string.Format("{0} [{1}]", sg.Name, sg.Id); + + + #line default + #line hidden +WriteLiteral(" (sg.IsGroup ? "group" : "user" + + #line default + #line hidden +, 14171), false) +); + +WriteLiteral(">"); + + + #line 298 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (sg.IsGroup) + { + + + #line default + #line hidden +WriteLiteral(" "); + + + #line 300 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 300 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(displayName); + + + #line default + #line hidden + + #line 300 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + } + else + { + + + #line default + #line hidden +WriteLiteral(" (Url.Action(MVC.User.Show(sg.Id)) + + #line default + #line hidden +, 14650), false) +); + +WriteLiteral(">"); + + + #line 304 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(displayName); + + + #line default + #line hidden +WriteLiteral("\r\n"); + + + #line 305 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + + #line default + #line hidden +WriteLiteral("\r\n"); + + + #line 306 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral(" \r\n"); + + + #line 308 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral(" "); + + + #line 309 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (canConfig) + { + + + #line default + #line hidden +WriteLiteral("
    \r\n Update\r\n \r\n \r\n None Associated\r\n \r\n"); + + + #line 317 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 317 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + foreach (var sg in Model.Subjects) + { + var displayName = sg.Id == sg.Name ? sg.Id : string.Format("{0} [{1}]", sg.Name, sg.Id); + + + #line default + #line hidden +WriteLiteral(" (sg.IsGroup ? "group" : "user" + + #line default + #line hidden +, 15827), false) +); + +WriteLiteral(" data-subjectid=\""); + + + #line 320 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(sg.Id); + + + #line default + #line hidden +WriteLiteral("\""); + +WriteLiteral(">"); + + + #line 320 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (sg.IsGroup) + { + + + #line default + #line hidden +WriteLiteral(" "); + + + #line 322 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 322 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(displayName); + + + #line default + #line hidden + + #line 322 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + } + else + { + + + #line default + #line hidden +WriteLiteral(" "); + + + #line 326 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 326 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(displayName); + + + #line default + #line hidden + + #line 326 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + } + + #line default + #line hidden +WriteLiteral("\r\n"); + + + #line 328 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral(" \r\n
    \r\n " + +" \r\n \r\n Add\r\n \r\n (Url.Action(MVC.API.JobQueue.UpdateSubjects(Model.Token.JobQueue.Id, null, true)) + + #line default + #line hidden +, 17259), false) +); + +WriteLiteral(" method=\"post\""); + +WriteLiteral(">\r\n \r\n \r\n \r\n"); + + + #line 490 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
    Automatically Add" + +" Jobs:\r\n
    \r\n"); + + + #line 497 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 497 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (Model.Token.JobQueue.JobSubTypes.Count > 0) + { + + + #line default + #line hidden +WriteLiteral("
      \r\n"); + + + #line 500 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 500 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + foreach (var jobType in Model.Token.JobQueue.JobSubTypes.GroupBy(jst => jst.JobType).OrderBy(jtg => jtg.Key.Description)) + { + + + #line default + #line hidden +WriteLiteral("
    • \r\n"); + +WriteLiteral(" "); + + + #line 503 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(jobType.Key.Description); + + + #line default + #line hidden +WriteLiteral("\r\n
        \r\n"); + + + #line 505 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 505 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (jobType.Count() == Model.JobTypes.FirstOrDefault(jt => jt.Id == jobType.Key.Id).JobSubTypes.Count) + { + + + #line default + #line hidden +WriteLiteral("
      • [All Sub Types]
      • \r\n"); + + + #line 508 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + else + { + foreach (var jobSubType in jobType) + { + + + #line default + #line hidden +WriteLiteral("
      • "); + + + #line 513 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(jobSubType.Description); + + + #line default + #line hidden +WriteLiteral("
      • \r\n"); + + + #line 514 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + } + + + #line default + #line hidden +WriteLiteral("
      \r\n
    • \r" + +"\n"); + + + #line 518 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
    \r\n"); + + + #line 520 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral(" "); + +WriteLiteral("<None>"); + +WriteLiteral("\r\n"); + + + #line 524 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral("
    \r\n"); + + + #line 526 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 526 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (canConfig) + { + + + #line default + #line hidden +WriteLiteral(" Update\r\n"); + +WriteLiteral(" \r\n"); + + + #line 530 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + + + #line default + #line hidden + + #line 530 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + using (Html.BeginForm(MVC.API.JobQueue.UpdateJobSubTypes(Model.Token.JobQueue.Id, null, true))) + { + var selectedTypes = Model.Token.JobQueue.JobSubTypes.Select(jst => jst.JobType).Distinct().ToList(); + foreach (var jt in Model.JobTypes) + { + + + #line default + #line hidden +WriteLiteral(" (jt.Id + + #line default + #line hidden +, 28079), false) +); + +WriteLiteral(" class=\"jobTypes\""); + +WriteLiteral(">\r\n

    \r\n (jt.Id + + #line default + #line hidden +, 28199), false) +); + +WriteLiteral(" class=\"jobType\""); + +WriteLiteral(" type=\"checkbox\""); + +WriteAttribute("value", Tuple.Create(" value=\"", 28240), Tuple.Create("\"", 28256) + + #line 537 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + , Tuple.Create(Tuple.Create("", 28248), Tuple.Create(jt.Id + + #line default + #line hidden +, 28248), false) +); + +WriteLiteral(" "); + + + #line 537 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(selectedTypes.Contains(jt) ? "checked=\"checked\"" : null); + + + #line default + #line hidden +WriteLiteral(" />(jt.Id + + #line default + #line hidden +, 28339), false) +); + +WriteLiteral(">"); + + + #line 537 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(jt.Description); + + + #line default + #line hidden +WriteLiteral("

    \r\n (jt.Id + + #line default + #line hidden +, 28429), false) +); + +WriteLiteral(" class=\"jobSubTypes\""); + +WriteLiteral(">\r\n"); + +WriteLiteral(" "); + + + #line 539 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(CommonHelpers.CheckboxBulkSelect(string.Format("CheckboxBulkSelect_{0}", jt.Id), "div")); + + + #line default + #line hidden +WriteLiteral("\r\n"); + +WriteLiteral(" "); + + + #line 540 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(CommonHelpers.CheckBoxList("JobSubTypes", jt.JobSubTypes.OrderBy(jst => jst.Description).ToSelectListItems(Model.Token.JobQueue.JobSubTypes), 2)); + + + #line default + #line hidden +WriteLiteral("\r\n \r\n \r\n" + +""); + + + #line 543 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + } + + + #line default + #line hidden +WriteLiteral(" \r\n"); + +WriteLiteral(" \r\n"); + + + #line 608 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + } + + + #line default + #line hidden +WriteLiteral(" \r\n  When jobs of these types are created, they will automatically be added" + +" into this queue.\r\n \r\n
    \r\n\r\n"); + + + #line 616 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + if (canDelete) +{ + + + #line default + #line hidden +WriteLiteral(" \r\n"); + +WriteLiteral(" "); + + + #line 619 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" + Write(Html.ActionLinkButton("Delete", MVC.API.JobQueue.Delete(Model.Token.JobQueue.Id, true), "Config_JobQueues_Actions_Delete_Button")); + + + #line default + #line hidden +WriteLiteral("\r\n \r\n

    \r\n \r\n This item will be permanently deleted and cannot be recove" + +"red.
    \r\n
    \r\n Are you sure?\r\n <" + +"/p>\r\n \r\n + $(function () { + var button = $('#Config_JobQueues_Actions_Delete_Button'); + var buttonDialog = $('#Config_JobQueues_Actions_Delete_Dialog'); + var buttonLink = button.attr('href'); + button.attr('href', '#'); + button.click(function () { + buttonDialog.dialog('open'); + return false; + }); + buttonDialog.dialog({ + resizable: false, + modal: true, + autoOpen: false, + buttons: { + ""Delete"": function () { + var $this = $(this); + $this.dialog(""disable""); + $this.dialog(""option"", ""buttons"", null); + window.location.href = buttonLink; + }, + Cancel: function () { + $(this).dialog(""close""); + } + } + }); + }); + + +"); + + + #line 657 "..\..\Areas\Config\Views\JobQueue\Show.cshtml" +} + + #line default + #line hidden + } + } +} +#pragma warning restore 1591 diff --git a/Disco.Web/Areas/Config/Views/Web.config b/Disco.Web/Areas/Config/Views/Web.config index d0d8e054..ec1c9143 100644 --- a/Disco.Web/Areas/Config/Views/Web.config +++ b/Disco.Web/Areas/Config/Views/Web.config @@ -15,6 +15,7 @@ + diff --git a/Disco.Web/Areas/Config/Views/_ViewStart.cshtml b/Disco.Web/Areas/Config/Views/_ViewStart.cshtml index eb41564f..18e97d77 100644 --- a/Disco.Web/Areas/Config/Views/_ViewStart.cshtml +++ b/Disco.Web/Areas/Config/Views/_ViewStart.cshtml @@ -1,4 +1,5 @@ @{ Layout = MVC.Shared.Views._Layout; Html.BundleDeferred("~/Style/Config"); + ViewContext.ViewData["MenuArea"] = MVC.Config.Name; } \ No newline at end of file diff --git a/Disco.Web/Areas/Config/Views/_ViewStart.generated.cs b/Disco.Web/Areas/Config/Views/_ViewStart.generated.cs index 5bf9664a..470afd22 100644 --- a/Disco.Web/Areas/Config/Views/_ViewStart.generated.cs +++ b/Disco.Web/Areas/Config/Views/_ViewStart.generated.cs @@ -48,6 +48,7 @@ namespace Disco.Web.Areas.Config.Views Layout = MVC.Shared.Views._Layout; Html.BundleDeferred("~/Style/Config"); + ViewContext.ViewData["MenuArea"] = MVC.Config.Name; #line default diff --git a/Disco.Web/Areas/Public/Views/Web.config b/Disco.Web/Areas/Public/Views/Web.config index 4d7bc926..13a39f1d 100644 --- a/Disco.Web/Areas/Public/Views/Web.config +++ b/Disco.Web/Areas/Public/Views/Web.config @@ -14,6 +14,7 @@ + diff --git a/Disco.Web/Areas/Public/Views/_ViewStart.cshtml b/Disco.Web/Areas/Public/Views/_ViewStart.cshtml index b06ec613..69c57fbf 100644 --- a/Disco.Web/Areas/Public/Views/_ViewStart.cshtml +++ b/Disco.Web/Areas/Public/Views/_ViewStart.cshtml @@ -1,3 +1,4 @@ @{ Layout = MVC.Shared.Views._PublicLayout; + ViewContext.ViewData["MenuArea"] = MVC.Public.Name; } \ No newline at end of file diff --git a/Disco.Web/Areas/Public/Views/_ViewStart.generated.cs b/Disco.Web/Areas/Public/Views/_ViewStart.generated.cs index c0510c80..9c44caea 100644 --- a/Disco.Web/Areas/Public/Views/_ViewStart.generated.cs +++ b/Disco.Web/Areas/Public/Views/_ViewStart.generated.cs @@ -46,6 +46,7 @@ namespace Disco.Web.Areas.Public.Views #line 1 "..\..\Areas\Public\Views\_ViewStart.cshtml" Layout = MVC.Shared.Views._PublicLayout; + ViewContext.ViewData["MenuArea"] = MVC.Public.Name; #line default diff --git a/Disco.Web/ClientSource/Scripts/Core.js b/Disco.Web/ClientSource/Scripts/Core.js index f553d09c..d52e8ea1 100644 --- a/Disco.Web/ClientSource/Scripts/Core.js +++ b/Disco.Web/ClientSource/Scripts/Core.js @@ -41952,7 +41952,7 @@ jQuery.fn.DataTable.defaults.aLengthMenu = [[10, 20, 50, -1], [10, 20, 50, "All" function subMenuShow() { var $this = $(this); - var $subMenu = $this.children('ul.subMenu'); + var $subMenu = $this.children('ul'); var hideToken = $this.data('menuHideToken'); if (hideToken) @@ -41963,7 +41963,7 @@ jQuery.fn.DataTable.defaults.aLengthMenu = [[10, 20, 50, -1], [10, 20, 50, "All" } function subMenuHide() { var $this = $(this); - var $subMenu = $this.children('ul.subMenu'); + var $subMenu = $this.children('ul'); var hideToken = window.setTimeout(function () { $subMenu.hide(); @@ -41974,7 +41974,7 @@ jQuery.fn.DataTable.defaults.aLengthMenu = [[10, 20, 50, -1], [10, 20, 50, "All" function subMenuTouchDown(e, preventClick) { var $this = $(this); var $link = $this.children('a'); - var $subMenu = $this.children('ul.subMenu'); + var $subMenu = $this.children('ul'); if (!$subMenu.is(':visible')) { @@ -41998,17 +41998,17 @@ jQuery.fn.DataTable.defaults.aLengthMenu = [[10, 20, 50, -1], [10, 20, 50, "All" if (Modernizr.hasEvent('pointerdown')) { // Pointer Events $menu - .on('pointerover', 'li.hasSubMenu', function (e) { + .on('pointerover', 'li.d-sm', function (e) { if (e.originalEvent.pointerType !== 'touch') { subMenuShow.call(this); } }) - .on('pointerout', 'li.hasSubMenu', function (e) { + .on('pointerout', 'li.d-sm', function (e) { if (e.originalEvent.pointerType !== 'touch') { subMenuHide.call(this); } }) - .on('pointerdown', 'li.hasSubMenu', function (e) { + .on('pointerdown', 'li.d-sm', function (e) { if (e.originalEvent.pointerType === 'touch') { return subMenuTouchDown.call(this, e, true); } @@ -42016,23 +42016,23 @@ jQuery.fn.DataTable.defaults.aLengthMenu = [[10, 20, 50, -1], [10, 20, 50, "All" $(document).on('pointerdown', function (e) { if (e.originalEvent.pointerType === 'touch') { if ($(e.target).closest('#menu').length == 0) - $menu.find('li.hasSubMenu>ul.subMenu:visible').hide(); + $menu.find('li.d-sm>ul.subMenu:visible').hide(); } }); } else if (Modernizr.hasEvent('mspointerdown')) { // MS Pointer Events $menu - .on('MSPointerOver', 'li.hasSubMenu', function (e) { + .on('MSPointerOver', 'li.d-sm', function (e) { if (e.originalEvent.pointerType !== e.originalEvent.MSPOINTER_TYPE_TOUCH) { subMenuShow.call(this); } }) - .on('MSPointerOut', 'li.hasSubMenu', function (e) { + .on('MSPointerOut', 'li.d-sm', function (e) { if (e.originalEvent.pointerType !== e.originalEvent.MSPOINTER_TYPE_TOUCH) { subMenuHide.call(this); } }) - .on('MSPointerDown', 'li.hasSubMenu', function (e) { + .on('MSPointerDown', 'li.d-sm', function (e) { if (e.originalEvent.pointerType === e.originalEvent.MSPOINTER_TYPE_TOUCH) { return subMenuTouchDown.call(this, e, true); } @@ -42040,22 +42040,22 @@ jQuery.fn.DataTable.defaults.aLengthMenu = [[10, 20, 50, -1], [10, 20, 50, "All" $(document).on('MSPointerDown', function (e) { if (e.originalEvent.pointerType === e.originalEvent.MSPOINTER_TYPE_TOUCH) { if ($(e.target).closest('#menu').length == 0) - $menu.find('li.hasSubMenu>ul.subMenu:visible').hide(); + $menu.find('li.d-sm>ul.subMenu:visible').hide(); } }); } else if (Modernizr.touch) { // Touch Events $menu - .on('mouseover', 'li.hasSubMenu', subMenuShow) - .on('mouseout', 'li.hasSubMenu', subMenuHide) - .on('touchstart', 'li.hasSubMenu', function (e) { + .on('mouseover', 'li.d-sm', subMenuShow) + .on('mouseout', 'li.d-sm', subMenuHide) + .on('touchstart', 'li.d-sm', function (e) { return subMenuTouchDown.call(this, e, false); }); } else { // Mouse Events $menu - .on('mouseover', 'li.hasSubMenu', subMenuShow) - .on('mouseout', 'li.hasSubMenu', subMenuHide); + .on('mouseover', 'li.d-sm', subMenuShow) + .on('mouseout', 'li.d-sm', subMenuHide); } } diff --git a/Disco.Web/ClientSource/Scripts/Core.min.js b/Disco.Web/ClientSource/Scripts/Core.min.js index 885a97b5..56edd378 100644 --- a/Disco.Web/ClientSource/Scripts/Core.min.js +++ b/Disco.Web/ClientSource/Scripts/Core.min.js @@ -1,4 +1,4 @@ -window.Modernizr=function(n,t,i){function a(n){c.cssText=n}function vt(n,t){return a(y.join(n+";")+(t||""))}function h(n,t){return typeof n===t}function v(n,t){return!!~(""+n).indexOf(t)}function lt(n,t){var u,r;for(u in n)if(r=n[u],!v(r,"-")&&c[r]!==i)return t=="pfx"?r:!0;return!1}function yt(n,t,r){var f,u;for(f in n)if(u=t[n[f]],u!==i)return r===!1?n[f]:h(u,"function")?u.bind(r||t):u;return!1}function f(n,t,i){var r=n.charAt(0).toUpperCase()+n.slice(1),u=(n+" "+ot.join(r+" ")+r).split(" ");return h(t,"string")||h(t,"undefined")?lt(u,t):(u=(n+" "+st.join(r+" ")+r).split(" "),yt(u,t,i))}function pt(){u.input=function(i){for(var r=0,u=i.length;r',n,"<\/style>"].join(""),f.id=e,(h?f:o).innerHTML+=l,o.appendChild(f),h||(o.style.background="",o.style.overflow="hidden",v=s.style.overflow,s.style.overflow="hidden",s.appendChild(o)),a=i(f,n),h?f.parentNode.removeChild(f):(o.parentNode.removeChild(o),s.style.overflow=v),!!a},at=function(t){var i=n.matchMedia||n.msMatchMedia,r;return i?i(t).matches:(l("@media "+t+" { #"+e+" { position: absolute; } }",function(t){r=(n.getComputedStyle?getComputedStyle(t,null):t.currentStyle).position=="absolute"}),r)},ct=function(){function r(r,u){u=u||t.createElement(n[r]||"div");r="on"+r;var f=r in u;return f||(u.setAttribute||(u=t.createElement("div")),u.setAttribute&&u.removeAttribute&&(u.setAttribute(r,""),f=h(u[r],"function"),h(u[r],"undefined")||(u[r]=i),u.removeAttribute(r))),u=null,f}var n={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return r}(),it={}.hasOwnProperty,rt,k;rt=h(it,"undefined")||h(it.call,"undefined")?function(n,t){return t in n&&h(n.constructor.prototype[t],"undefined")}:function(n,t){return it.call(n,t)};Function.prototype.bind||(Function.prototype.bind=function(n){var t=this,i,r;if(typeof t!="function")throw new TypeError;return i=tt.call(arguments,1),r=function(){var f,e,u;return this instanceof r?(f=function(){},f.prototype=t.prototype,e=new f,u=t.apply(e,i.concat(tt.call(arguments))),Object(u)===u)?u:e:t.apply(n,i.concat(tt.call(arguments)))},r});r.flexbox=function(){return f("flexWrap")};r.flexboxlegacy=function(){return f("boxDirection")};r.canvas=function(){var n=t.createElement("canvas");return!!(n.getContext&&n.getContext("2d"))};r.canvastext=function(){return!!(u.canvas&&h(t.createElement("canvas").getContext("2d").fillText,"function"))};r.webgl=function(){return!!n.WebGLRenderingContext};r.touch=function(){var i;return"ontouchstart"in n||n.DocumentTouch&&t instanceof DocumentTouch?i=!0:l(["@media (",y.join("touch-enabled),("),e,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(n){i=n.offsetTop===9}),i};r.geolocation=function(){return"geolocation"in navigator};r.postmessage=function(){return!!n.postMessage};r.websqldatabase=function(){return!!n.openDatabase};r.indexedDB=function(){return!!f("indexedDB",n)};r.hashchange=function(){return ct("hashchange",n)&&(t.documentMode===i||t.documentMode>7)};r.history=function(){return!!(n.history&&history.pushState)};r.draganddrop=function(){var n=t.createElement("div");return"draggable"in n||"ondragstart"in n&&"ondrop"in n};r.websockets=function(){return"WebSocket"in n||"MozWebSocket"in n};r.rgba=function(){return a("background-color:rgba(150,255,150,.5)"),v(c.backgroundColor,"rgba")};r.hsla=function(){return a("background-color:hsla(120,40%,100%,.5)"),v(c.backgroundColor,"rgba")||v(c.backgroundColor,"hsla")};r.multiplebgs=function(){return a("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(c.background)};r.backgroundsize=function(){return f("backgroundSize")};r.borderimage=function(){return f("borderImage")};r.borderradius=function(){return f("borderRadius")};r.boxshadow=function(){return f("boxShadow")};r.textshadow=function(){return t.createElement("div").style.textShadow===""};r.opacity=function(){return vt("opacity:.55"),/^0.55$/.test(c.opacity)};r.cssanimations=function(){return f("animationName")};r.csscolumns=function(){return f("columnCount")};r.cssgradients=function(){var n="background-image:";return a((n+"-webkit- ".split(" ").join("gradient(linear,left top,right bottom,from(#9f9),to(white));"+n)+y.join("linear-gradient(left top,#9f9, white);"+n)).slice(0,-n.length)),v(c.backgroundImage,"gradient")};r.cssreflections=function(){return f("boxReflect")};r.csstransforms=function(){return!!f("transform")};r.csstransforms3d=function(){var n=!!f("perspective");return n&&"webkitPerspective"in s.style&&l("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(t){n=t.offsetLeft===9&&t.offsetHeight===3}),n};r.csstransitions=function(){return f("transition")};r.fontface=function(){var n;return l('@font-face {font-family:"font";src:url("https://")}',function(i,r){var f=t.getElementById("smodernizr"),u=f.sheet||f.styleSheet,e=u?u.cssRules&&u.cssRules[0]?u.cssRules[0].cssText:u.cssText||"":"";n=/src/i.test(e)&&e.indexOf(r.split(" ")[0])===0}),n};r.generatedcontent=function(){var n;return l(["#",e,"{font:0/0 a}#",e,':after{content:"',g,'";visibility:hidden;font:3px/1 a}'].join(""),function(t){n=t.offsetHeight>=3}),n};r.video=function(){var i=t.createElement("video"),n=!1;try{(n=!!i.canPlayType)&&(n=new Boolean(n),n.ogg=i.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),n.h264=i.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),n.webm=i.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,""))}catch(r){}return n};r.audio=function(){var i=t.createElement("audio"),n=!1;try{(n=!!i.canPlayType)&&(n=new Boolean(n),n.ogg=i.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),n.mp3=i.canPlayType("audio/mpeg;").replace(/^no$/,""),n.wav=i.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),n.m4a=(i.canPlayType("audio/x-m4a;")||i.canPlayType("audio/aac;")).replace(/^no$/,""))}catch(r){}return n};r.localstorage=function(){try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(n){return!1}};r.sessionstorage=function(){try{return sessionStorage.setItem(e,e),sessionStorage.removeItem(e),!0}catch(n){return!1}};r.webworkers=function(){return!!n.Worker};r.applicationcache=function(){return!!n.applicationCache};r.svg=function(){return!!t.createElementNS&&!!t.createElementNS(p.svg,"svg").createSVGRect};r.inlinesvg=function(){var n=t.createElement("div");return n.innerHTML="",(n.firstChild&&n.firstChild.namespaceURI)==p.svg};r.smil=function(){return!!t.createElementNS&&/SVGAnimate/.test(ft.call(t.createElementNS(p.svg,"animate")))};r.svgclippaths=function(){return!!t.createElementNS&&/SVGClipPath/.test(ft.call(t.createElementNS(p.svg,"clipPath")))};for(k in r)rt(r,k)&&(b=k.toLowerCase(),u[b]=r[k](),nt.push((u[b]?"":"no-")+b));return u.input||pt(),u.addTest=function(n,t){if(typeof n=="object")for(var r in n)rt(n,r)&&u.addTest(r,n[r]);else{if(n=n.toLowerCase(),u[n]!==i)return u;t=typeof t=="function"?t():t;typeof d!="undefined"&&d&&(s.className+=" "+(t?"":"no-")+n);u[n]=t}return u},a(""),ut=o=null,function(n,t){function p(n,t){var i=n.createElement("p"),r=n.getElementsByTagName("head")[0]||n.documentElement;return i.innerHTML="x