#145 add comments for devices

This commit is contained in:
Gary Sharp
2025-07-17 11:40:50 +10:00
parent 2184c9e22e
commit f8fd1a58a3
35 changed files with 2047 additions and 614 deletions
+33 -1
View File
@@ -193,6 +193,7 @@ namespace Disco.Services.Authorization
{ "Device.Properties.DeviceProfile", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Properties.DeviceProfile, (c, v) => c.Device.Properties.DeviceProfile = v, "Device Profile Property", "Can update property", false) }, { "Device.Properties.DeviceProfile", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Properties.DeviceProfile, (c, v) => c.Device.Properties.DeviceProfile = v, "Device Profile Property", "Can update property", false) },
{ "Device.Properties.Location", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Properties.Location, (c, v) => c.Device.Properties.Location = v, "Location Property", "Can update property", false) }, { "Device.Properties.Location", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Properties.Location, (c, v) => c.Device.Properties.Location = v, "Location Property", "Can update property", false) },
{ "Device.Actions.AddAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AddAttachments, (c, v) => c.Device.Actions.AddAttachments = v, "Add Attachments", "Can add attachments to devices", false) }, { "Device.Actions.AddAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AddAttachments, (c, v) => c.Device.Actions.AddAttachments = v, "Add Attachments", "Can add attachments to devices", false) },
{ "Device.Actions.AddComments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AddComments, (c, v) => c.Device.Actions.AddComments = v, "Add Comments", "Can add device comments", false) },
{ "Device.Actions.AddFlags", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AddFlags, (c, v) => c.Device.Actions.AddFlags = v, "Add Device Flags", "Can add device flags", false) }, { "Device.Actions.AddFlags", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AddFlags, (c, v) => c.Device.Actions.AddFlags = v, "Add Device Flags", "Can add device flags", false) },
{ "Device.Actions.AllowUnauthenticatedEnrol", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AllowUnauthenticatedEnrol, (c, v) => c.Device.Actions.AllowUnauthenticatedEnrol = v, "Allow Unauthenticated Enrol", "Can allow devices to enrol without authentication", false) }, { "Device.Actions.AllowUnauthenticatedEnrol", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AllowUnauthenticatedEnrol, (c, v) => c.Device.Actions.AllowUnauthenticatedEnrol = v, "Allow Unauthenticated Enrol", "Can allow devices to enrol without authentication", false) },
{ "Device.Actions.AssignUser", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AssignUser, (c, v) => c.Device.Actions.AssignUser = v, "Assign User", "Can update the user assignment of devices", false) }, { "Device.Actions.AssignUser", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.AssignUser, (c, v) => c.Device.Actions.AssignUser = v, "Assign User", "Can update the user assignment of devices", false) },
@@ -205,12 +206,15 @@ namespace Disco.Services.Authorization
{ "Device.Actions.Import", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Import, (c, v) => c.Device.Actions.Import = v, "Import Devices", "Can bulk import devices", false) }, { "Device.Actions.Import", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Import, (c, v) => c.Device.Actions.Import = v, "Import Devices", "Can bulk import devices", false) },
{ "Device.Actions.Recommission", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Recommission, (c, v) => c.Device.Actions.Recommission = v, "Recommission", "Can recommission devices", false) }, { "Device.Actions.Recommission", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.Recommission, (c, v) => c.Device.Actions.Recommission = v, "Recommission", "Can recommission devices", false) },
{ "Device.Actions.RemoveAnyAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveAnyAttachments, (c, v) => c.Device.Actions.RemoveAnyAttachments = v, "Remove Any Attachments", "Can remove any attachments from devices", false) }, { "Device.Actions.RemoveAnyAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveAnyAttachments, (c, v) => c.Device.Actions.RemoveAnyAttachments = v, "Remove Any Attachments", "Can remove any attachments from devices", false) },
{ "Device.Actions.RemoveAnyComments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveAnyComments, (c, v) => c.Device.Actions.RemoveAnyComments = v, "Remove Any Comments", "Can remove any device comments", false) },
{ "Device.Actions.RemoveFlags", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveFlags, (c, v) => c.Device.Actions.RemoveFlags = v, "Remove Device Flags", "Can remove device flags", false) }, { "Device.Actions.RemoveFlags", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveFlags, (c, v) => c.Device.Actions.RemoveFlags = v, "Remove Device Flags", "Can remove device flags", false) },
{ "Device.Actions.RemoveOwnAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveOwnAttachments, (c, v) => c.Device.Actions.RemoveOwnAttachments = v, "Remove Own Attachments", "Can remove own attachments from devices", false) }, { "Device.Actions.RemoveOwnAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveOwnAttachments, (c, v) => c.Device.Actions.RemoveOwnAttachments = v, "Remove Own Attachments", "Can remove own attachments from devices", false) },
{ "Device.Actions.RemoveOwnComments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Actions.RemoveOwnComments, (c, v) => c.Device.Actions.RemoveOwnComments = v, "Remove Own Comments", "Can remove own device comments", false) },
{ "Device.Search", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Search, (c, v) => c.Device.Search = v, "Search Devices", "Can search devices", false) }, { "Device.Search", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Search, (c, v) => c.Device.Search = v, "Search Devices", "Can search devices", false) },
{ "Device.ShowAssignmentHistory", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowAssignmentHistory, (c, v) => c.Device.ShowAssignmentHistory = v, "Show Assignment History", "Can show the assignment history for devices", false) }, { "Device.ShowAssignmentHistory", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowAssignmentHistory, (c, v) => c.Device.ShowAssignmentHistory = v, "Show Assignment History", "Can show the assignment history for devices", false) },
{ "Device.ShowAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowAttachments, (c, v) => c.Device.ShowAttachments = v, "Show Attachments", "Can show device attachments", false) }, { "Device.ShowAttachments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowAttachments, (c, v) => c.Device.ShowAttachments = v, "Show Attachments", "Can show device attachments", false) },
{ "Device.ShowCertificates", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowCertificates, (c, v) => c.Device.ShowCertificates = v, "Show Certificates", "Can show certificates associated with devices", false) }, { "Device.ShowCertificates", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowCertificates, (c, v) => c.Device.ShowCertificates = v, "Show Certificates", "Can show certificates associated with devices", false) },
{ "Device.ShowComments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowComments, (c, v) => c.Device.ShowComments = v, "Show Comments", "Can show device comments", false) },
{ "Device.ShowDetails", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowDetails, (c, v) => c.Device.ShowDetails = v, "Show Details", "Can show details associated with devices", false) }, { "Device.ShowDetails", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowDetails, (c, v) => c.Device.ShowDetails = v, "Show Details", "Can show details associated with devices", false) },
{ "Device.ShowFlagAssignments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowFlagAssignments, (c, v) => c.Device.ShowFlagAssignments = v, "Show Device Flag Assignments", "Can show flags associated with devices", false) }, { "Device.ShowFlagAssignments", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.ShowFlagAssignments, (c, v) => c.Device.ShowFlagAssignments = v, "Show Device Flag Assignments", "Can show flags associated with devices", false) },
{ "Device.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Show, (c, v) => c.Device.Show = v, "Show Devices", "Can show devices", false) }, { "Device.Show", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Device.Show, (c, v) => c.Device.Show = v, "Show Devices", "Can show devices", false) },
@@ -458,6 +462,7 @@ namespace Disco.Services.Authorization
new ClaimNavigatorItem("Device", "Device", "Permissions related to Devices", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Device", "Device", "Permissions related to Devices", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Device.Actions", "Actions", "Permissions related to Device Actions", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Device.Actions", "Actions", "Permissions related to Device Actions", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Device.Actions.AddAttachments", false), new ClaimNavigatorItem("Device.Actions.AddAttachments", false),
new ClaimNavigatorItem("Device.Actions.AddComments", false),
new ClaimNavigatorItem("Device.Actions.AddFlags", false), new ClaimNavigatorItem("Device.Actions.AddFlags", false),
new ClaimNavigatorItem("Device.Actions.AllowUnauthenticatedEnrol", false), new ClaimNavigatorItem("Device.Actions.AllowUnauthenticatedEnrol", false),
new ClaimNavigatorItem("Device.Actions.AssignUser", false), new ClaimNavigatorItem("Device.Actions.AssignUser", false),
@@ -470,8 +475,10 @@ namespace Disco.Services.Authorization
new ClaimNavigatorItem("Device.Actions.Import", false), new ClaimNavigatorItem("Device.Actions.Import", false),
new ClaimNavigatorItem("Device.Actions.Recommission", false), new ClaimNavigatorItem("Device.Actions.Recommission", false),
new ClaimNavigatorItem("Device.Actions.RemoveAnyAttachments", false), new ClaimNavigatorItem("Device.Actions.RemoveAnyAttachments", false),
new ClaimNavigatorItem("Device.Actions.RemoveAnyComments", false),
new ClaimNavigatorItem("Device.Actions.RemoveFlags", false), new ClaimNavigatorItem("Device.Actions.RemoveFlags", false),
new ClaimNavigatorItem("Device.Actions.RemoveOwnAttachments", false) new ClaimNavigatorItem("Device.Actions.RemoveOwnAttachments", false),
new ClaimNavigatorItem("Device.Actions.RemoveOwnComments", false)
}), }),
new ClaimNavigatorItem("Device.Properties", "Device Properties", "Permissions related to Device Properties", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Device.Properties", "Device Properties", "Permissions related to Device Properties", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Device.Properties.AssetNumber", false), new ClaimNavigatorItem("Device.Properties.AssetNumber", false),
@@ -484,6 +491,7 @@ namespace Disco.Services.Authorization
new ClaimNavigatorItem("Device.ShowAssignmentHistory", false), new ClaimNavigatorItem("Device.ShowAssignmentHistory", false),
new ClaimNavigatorItem("Device.ShowAttachments", false), new ClaimNavigatorItem("Device.ShowAttachments", false),
new ClaimNavigatorItem("Device.ShowCertificates", false), new ClaimNavigatorItem("Device.ShowCertificates", false),
new ClaimNavigatorItem("Device.ShowComments", false),
new ClaimNavigatorItem("Device.ShowDetails", false), new ClaimNavigatorItem("Device.ShowDetails", false),
new ClaimNavigatorItem("Device.ShowFlagAssignments", false), new ClaimNavigatorItem("Device.ShowFlagAssignments", false),
new ClaimNavigatorItem("Device.Show", false), new ClaimNavigatorItem("Device.Show", false),
@@ -749,6 +757,7 @@ namespace Disco.Services.Authorization
c.Device.Properties.DeviceProfile = true; c.Device.Properties.DeviceProfile = true;
c.Device.Properties.Location = true; c.Device.Properties.Location = true;
c.Device.Actions.AddAttachments = true; c.Device.Actions.AddAttachments = true;
c.Device.Actions.AddComments = true;
c.Device.Actions.AddFlags = true; c.Device.Actions.AddFlags = true;
c.Device.Actions.AllowUnauthenticatedEnrol = true; c.Device.Actions.AllowUnauthenticatedEnrol = true;
c.Device.Actions.AssignUser = true; c.Device.Actions.AssignUser = true;
@@ -761,12 +770,15 @@ namespace Disco.Services.Authorization
c.Device.Actions.Import = true; c.Device.Actions.Import = true;
c.Device.Actions.Recommission = true; c.Device.Actions.Recommission = true;
c.Device.Actions.RemoveAnyAttachments = true; c.Device.Actions.RemoveAnyAttachments = true;
c.Device.Actions.RemoveAnyComments = true;
c.Device.Actions.RemoveFlags = true; c.Device.Actions.RemoveFlags = true;
c.Device.Actions.RemoveOwnAttachments = true; c.Device.Actions.RemoveOwnAttachments = true;
c.Device.Actions.RemoveOwnComments = true;
c.Device.Search = true; c.Device.Search = true;
c.Device.ShowAssignmentHistory = true; c.Device.ShowAssignmentHistory = true;
c.Device.ShowAttachments = true; c.Device.ShowAttachments = true;
c.Device.ShowCertificates = true; c.Device.ShowCertificates = true;
c.Device.ShowComments = true;
c.Device.ShowDetails = true; c.Device.ShowDetails = true;
c.Device.ShowFlagAssignments = true; c.Device.ShowFlagAssignments = true;
c.Device.Show = true; c.Device.Show = true;
@@ -1844,6 +1856,11 @@ namespace Disco.Services.Authorization
/// </summary> /// </summary>
public const string AddAttachments = "Device.Actions.AddAttachments"; public const string AddAttachments = "Device.Actions.AddAttachments";
/// <summary>Add Comments
/// <para>Can add device comments</para>
/// </summary>
public const string AddComments = "Device.Actions.AddComments";
/// <summary>Add Device Flags /// <summary>Add Device Flags
/// <para>Can add device flags</para> /// <para>Can add device flags</para>
/// </summary> /// </summary>
@@ -1904,6 +1921,11 @@ namespace Disco.Services.Authorization
/// </summary> /// </summary>
public const string RemoveAnyAttachments = "Device.Actions.RemoveAnyAttachments"; public const string RemoveAnyAttachments = "Device.Actions.RemoveAnyAttachments";
/// <summary>Remove Any Comments
/// <para>Can remove any device comments</para>
/// </summary>
public const string RemoveAnyComments = "Device.Actions.RemoveAnyComments";
/// <summary>Remove Device Flags /// <summary>Remove Device Flags
/// <para>Can remove device flags</para> /// <para>Can remove device flags</para>
/// </summary> /// </summary>
@@ -1913,6 +1935,11 @@ namespace Disco.Services.Authorization
/// <para>Can remove own attachments from devices</para> /// <para>Can remove own attachments from devices</para>
/// </summary> /// </summary>
public const string RemoveOwnAttachments = "Device.Actions.RemoveOwnAttachments"; public const string RemoveOwnAttachments = "Device.Actions.RemoveOwnAttachments";
/// <summary>Remove Own Comments
/// <para>Can remove own device comments</para>
/// </summary>
public const string RemoveOwnComments = "Device.Actions.RemoveOwnComments";
} }
/// <summary>Search Devices /// <summary>Search Devices
@@ -1935,6 +1962,11 @@ namespace Disco.Services.Authorization
/// </summary> /// </summary>
public const string ShowCertificates = "Device.ShowCertificates"; public const string ShowCertificates = "Device.ShowCertificates";
/// <summary>Show Comments
/// <para>Can show device comments</para>
/// </summary>
public const string ShowComments = "Device.ShowComments";
/// <summary>Show Details /// <summary>Show Details
/// <para>Can show details associated with devices</para> /// <para>Can show details associated with devices</para>
/// </summary> /// </summary>
@@ -16,6 +16,13 @@
[ClaimDetails("Delete", "Can delete devices")] [ClaimDetails("Delete", "Can delete devices")]
public bool Delete { get; set; } public bool Delete { get; set; }
[ClaimDetails("Add Comments", "Can add device comments")]
public bool AddComments { get; set; }
[ClaimDetails("Remove Any Comments", "Can remove any device comments")]
public bool RemoveAnyComments { get; set; }
[ClaimDetails("Remove Own Comments", "Can remove own device comments")]
public bool RemoveOwnComments { get; set; }
[ClaimDetails("Add Attachments", "Can add attachments to devices")] [ClaimDetails("Add Attachments", "Can add attachments to devices")]
public bool AddAttachments { get; set; } public bool AddAttachments { get; set; }
[ClaimDetails("Remove Any Attachments", "Can remove any attachments from devices")] [ClaimDetails("Remove Any Attachments", "Can remove any attachments from devices")]
@@ -17,6 +17,8 @@
[ClaimDetails("Show Details", "Can show details associated with devices")] [ClaimDetails("Show Details", "Can show details associated with devices")]
public bool ShowDetails { get; set; } public bool ShowDetails { get; set; }
[ClaimDetails("Show Comments", "Can show device comments")]
public bool ShowComments { get; set; }
[ClaimDetails("Show Attachments", "Can show device attachments")] [ClaimDetails("Show Attachments", "Can show device attachments")]
public bool ShowAttachments { get; set; } public bool ShowAttachments { get; set; }
[ClaimDetails("Show Certificates", "Can show certificates associated with devices")] [ClaimDetails("Show Certificates", "Can show certificates associated with devices")]
+59 -30
View File
@@ -1,7 +1,7 @@
using Disco.Data.Repository; using Disco.Data.Repository.Monitor;
using Disco.Data.Repository.Monitor;
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Services.Authorization; using Disco.Services.Authorization;
using Disco.Services.Users;
using Disco.Services.Web.Signalling; using Disco.Services.Web.Signalling;
using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs; using Microsoft.AspNet.SignalR.Hubs;
@@ -12,14 +12,13 @@ using System.Threading.Tasks;
namespace Disco.Services.Devices namespace Disco.Services.Devices
{ {
[HubName("deviceUpdates"), DiscoHubAuthorizeAll(Claims.Device.Show, Claims.Device.ShowAttachments)] [HubName("deviceUpdates"), DiscoHubAuthorize(Claims.Device.Show)]
public class DeviceUpdatesHub : Hub public class DeviceUpdatesHub : Hub
{ {
private const string UserPrefix = "Device_"; public static IHubContext HubContext { get; }
public static IHubContext HubContext { get; private set; }
private static IDisposable RepositoryBeforeSubscription; private readonly static IDisposable RepositoryBeforeSubscription;
private static IDisposable RepositoryAfterSubscription; private readonly static IDisposable RepositoryAfterSubscription;
static DeviceUpdatesHub() static DeviceUpdatesHub()
{ {
@@ -27,18 +26,51 @@ namespace Disco.Services.Devices
// Subscribe to Repository Monitor for Changes // Subscribe to Repository Monitor for Changes
RepositoryBeforeSubscription = RepositoryMonitor.StreamBeforeCommit RepositoryBeforeSubscription = RepositoryMonitor.StreamBeforeCommit
.Where(e => e.EntityType == typeof(DeviceAttachment) && e.EventType == RepositoryMonitorEventType.Deleted) .Where(e =>
.Subscribe(RepositoryEventBefore); e.EventType == RepositoryMonitorEventType.Deleted && (
e.EntityType == typeof(DeviceComment) ||
e.EntityType == typeof(DeviceAttachment)
)
).Subscribe(RepositoryEventBefore);
RepositoryAfterSubscription = RepositoryMonitor.StreamAfterCommit RepositoryAfterSubscription = RepositoryMonitor.StreamAfterCommit
.Where(e => e.EntityType == typeof(DeviceAttachment) && e.EventType == RepositoryMonitorEventType.Added) .Where(e =>
.Subscribe(RepositoryAfterEvent); e.EventType == RepositoryMonitorEventType.Added && (
e.EntityType == typeof(DeviceComment) ||
e.EntityType == typeof(DeviceAttachment)
)
).Subscribe(RepositoryAfterEvent);
} }
private static string GroupName(string DeviceSerialNumber) private static bool TryAttachmentGroupName(RepositoryMonitorEvent e, out string groupName)
{ {
return UserPrefix + DeviceSerialNumber; var deviceSerialNumber = e.GetPreviousPropertyValue<string>(nameof(DeviceAttachment.DeviceSerialNumber));
if (deviceSerialNumber == null)
{
groupName = null;
return false;
}
groupName = AttachmentGroupName(deviceSerialNumber);
return true;
} }
private static string AttachmentGroupName(string deviceSerialNumber)
=> $"Device_Attachment_{deviceSerialNumber.ToLowerInvariant()}";
private static bool TryCommentGroupName(RepositoryMonitorEvent e, out string groupName)
{
var deviceSerialNumber = e.GetPreviousPropertyValue<string>(nameof(DeviceComment.DeviceSerialNumber));
if (deviceSerialNumber == null)
{
groupName = null;
return false;
}
groupName = CommentGroupName(deviceSerialNumber);
return true;
}
private static string CommentGroupName(string deviceSerialNumber)
=> $"Device_Comment_{deviceSerialNumber.ToLowerInvariant()}";
public override Task OnConnected() public override Task OnConnected()
{ {
var deviceSerialNumber = Context.QueryString["DeviceSerialNumber"]; var deviceSerialNumber = Context.QueryString["DeviceSerialNumber"];
@@ -46,7 +78,12 @@ namespace Disco.Services.Devices
if (string.IsNullOrWhiteSpace(deviceSerialNumber)) if (string.IsNullOrWhiteSpace(deviceSerialNumber))
throw new ArgumentNullException("DeviceSerialNumber"); throw new ArgumentNullException("DeviceSerialNumber");
Groups.Add(Context.ConnectionId, GroupName(deviceSerialNumber)); var authorization = UserService.GetAuthorization(Context.User.Identity.Name);
if (authorization.Has(Claims.Device.ShowComments))
Groups.Add(Context.ConnectionId, CommentGroupName(deviceSerialNumber));
if (authorization.Has(Claims.Device.ShowAttachments))
Groups.Add(Context.ConnectionId, AttachmentGroupName(deviceSerialNumber));
return base.OnConnected(); return base.OnConnected();
} }
@@ -55,16 +92,10 @@ namespace Disco.Services.Devices
{ {
if (e.EventType == RepositoryMonitorEventType.Deleted) if (e.EventType == RepositoryMonitorEventType.Deleted)
{ {
if (e.EntityType == typeof(DeviceAttachment)) if (e.Entity is DeviceComment comment && TryCommentGroupName(e, out var commentGroupName))
{ HubContext.Clients.Group(commentGroupName).commentRemoved(comment.Id);
var repositoryAttachment = (DeviceAttachment)e.Entity; else if (e.Entity is DeviceAttachment attachment && TryAttachmentGroupName(e, out var attachmentGroupName))
string attachmentDeviceSerialNumber; HubContext.Clients.Group(attachmentGroupName).attachmentRemoved(attachment.Id);
using (DiscoDataContext Database = new DiscoDataContext())
attachmentDeviceSerialNumber = Database.DeviceAttachments.Where(a => a.Id == repositoryAttachment.Id).Select(a => a.DeviceSerialNumber).First();
HubContext.Clients.Group(GroupName(attachmentDeviceSerialNumber)).removeAttachment(repositoryAttachment.Id);
}
} }
} }
@@ -72,12 +103,10 @@ namespace Disco.Services.Devices
{ {
if (e.EventType == RepositoryMonitorEventType.Added) if (e.EventType == RepositoryMonitorEventType.Added)
{ {
if (e.EntityType == typeof(DeviceAttachment)) if (e.Entity is DeviceComment comment)
{ HubContext.Clients.Group(CommentGroupName(comment.DeviceSerialNumber)).commentAdded(comment.Id);
var a = (DeviceAttachment)e.Entity; else if (e.Entity is DeviceAttachment attachment)
HubContext.Clients.Group(AttachmentGroupName(attachment.DeviceSerialNumber)).attachmentAdded(attachment.Id);
HubContext.Clients.Group(GroupName(a.DeviceSerialNumber)).addAttachment(a.Id);
}
} }
} }
} }
+5 -5
View File
@@ -14,7 +14,7 @@ namespace Disco.Services.Users
[HubName("userUpdates"), DiscoHubAuthorize(Claims.User.Show)] [HubName("userUpdates"), DiscoHubAuthorize(Claims.User.Show)]
public class UserUpdatesHub : Hub public class UserUpdatesHub : Hub
{ {
public static IHubContext HubContext { get; private set; } public static IHubContext HubContext { get; }
private static readonly IDisposable repositoryBeforeSubscription; private static readonly IDisposable repositoryBeforeSubscription;
private static readonly IDisposable repositoryAfterSubscription; private static readonly IDisposable repositoryAfterSubscription;
@@ -52,8 +52,8 @@ namespace Disco.Services.Users
return true; return true;
} }
private static string AttachmentGroupName(string UserId) private static string AttachmentGroupName(string userId)
=> $"User_Attachment_{UserId.ToLowerInvariant()}"; => $"User_Attachment_{userId.ToLowerInvariant()}";
private static bool TryCommentGroupName(RepositoryMonitorEvent e, out string groupName) private static bool TryCommentGroupName(RepositoryMonitorEvent e, out string groupName)
{ {
@@ -67,8 +67,8 @@ namespace Disco.Services.Users
return true; return true;
} }
private static string CommentGroupName(string UserId) private static string CommentGroupName(string userId)
=> $"User_Comment_{UserId.ToLowerInvariant()}"; => $"User_Comment_{userId.ToLowerInvariant()}";
public override Task OnConnected() public override Task OnConnected()
{ {
@@ -472,7 +472,88 @@ namespace Disco.Web.Areas.API.Controllers
return Json(result, JsonRequestBehavior.AllowGet); return Json(result, JsonRequestBehavior.AllowGet);
} }
#region Device Attachements #region Device Comments
[DiscoAuthorize(Claims.Device.ShowComments)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult Comments(string id)
{
if (string.IsNullOrEmpty(id))
throw new ArgumentNullException(nameof(id));
var device = Database.Devices
.Include(d => d.DeviceComments.Select(l => l.TechUser))
.Where(d => d.SerialNumber == id).FirstOrDefault();
if (device == null)
return BadRequest("Invalid Device Serial Number");
var results = device.DeviceComments.OrderByDescending(c => c.Timestamp).Select(c => Models.Shared.CommentModel.FromEntity(c)).ToList();
return Json(results);
}
[DiscoAuthorize(Claims.Device.ShowComments)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult Comment(int id)
{
var entity = Database.DeviceComments
.Include(c => c.TechUser)
.FirstOrDefault(c => c.Id == id);
if (entity == null)
return BadRequest("Invalid Device Comment Id");
var comment = Models.Shared.CommentModel.FromEntity(entity);
return Json(comment);
}
[DiscoAuthorize(Claims.Device.Actions.AddComments)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult CommentAdd(string id, string comment = null)
{
if (string.IsNullOrEmpty(id))
throw new ArgumentNullException(nameof(id));
if (string.IsNullOrWhiteSpace(comment))
return BadRequest("Comment is required");
var device = Database.Devices.Find(id);
if (device == null)
return BadRequest("Invalid Device Serial Number");
var entity = new DeviceComment()
{
DeviceSerialNumber = device.SerialNumber,
TechUserId = CurrentUser.UserId,
Timestamp = DateTime.Now,
Comments = comment
};
Database.DeviceComments.Add(entity);
Database.SaveChanges();
return Json(entity.Id);
}
[DiscoAuthorizeAny(Claims.Device.Actions.RemoveAnyComments, Claims.Device.Actions.RemoveOwnComments)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult CommentRemove(int id)
{
var entity = Database.DeviceComments.Find(id);
if (entity != null)
{
if (entity.TechUserId.Equals(CurrentUser.UserId, StringComparison.OrdinalIgnoreCase))
Authorization.RequireAny(Claims.Device.Actions.RemoveAnyComments, Claims.Device.Actions.RemoveOwnComments);
else
Authorization.Require(Claims.Device.Actions.RemoveAnyComments);
Database.DeviceComments.Remove(entity);
Database.SaveChanges();
}
// Doesn't Exist/Already Deleted - OK
return Ok();
}
#endregion
#region Device Attachments
[DiscoAuthorize(Claims.Device.ShowAttachments), OutputCache(Location = System.Web.UI.OutputCacheLocation.Client, Duration = 172800)] [DiscoAuthorize(Claims.Device.ShowAttachments), OutputCache(Location = System.Web.UI.OutputCacheLocation.Client, Duration = 172800)]
public virtual ActionResult AttachmentDownload(int id) public virtual ActionResult AttachmentDownload(int id)
@@ -46,5 +46,19 @@ namespace Disco.Web.Areas.API.Models.Shared
}; };
} }
public static CommentModel FromEntity(DeviceComment comment)
{
return new CommentModel
{
Id = comment.Id,
TargetType = AttachmentTypes.Device,
TargetId = comment.DeviceSerialNumber,
AuthorId = comment.TechUserId,
Author = comment.TechUser.ToString(),
Timestamp = comment.Timestamp,
Comments = comment.Comments,
HtmlComments = comment.Comments.ToHtmlComment().ToString()
};
}
} }
} }
+144 -2
View File
@@ -206,6 +206,146 @@
border-top: none; border-top: none;
background-color: #eee; background-color: #eee;
} }
#DeviceDetailTab-CommentsAndJobs {
display: grid;
grid-template-columns: auto;
}
#DeviceDetailTab-CommentsAndJobs.canShowComments.canShowJobs {
grid-template-columns: 375px auto;
}
#DeviceDetailTab-CommentsAndJobs.canShowComments.canShowJobs > #DeviceDetailTab-Comments {
grid-column: 1;
}
#DeviceDetailTab-CommentsAndJobs.canShowComments.canShowJobs > #DeviceDetailTab-JobsContainer {
grid-column: 2;
}
#DeviceDetailTab-CommentsAndJobs.cannotShowComments div.jobTable {
border: 1px solid #ccc;
}
#DeviceDetailTab-CommentsContainer {
max-height: 650px;
}
#DeviceDetailTab-JobsContainer {
max-height: 650px;
overflow: auto;
}
#Comments {
box-sizing: border-box;
height: 100%;
min-height: 373px;
padding-bottom: 51px;
border: 1px solid #ccc;
background-color: #fff;
position: relative;
}
#Comments div.commentInput {
border-top: 1px solid #ccc;
box-sizing: border-box;
width: 100%;
height: 51px;
padding: 5px;
position: absolute;
bottom: 0;
display: grid;
grid-template-columns: auto 40px;
}
#Comments div.commentInput textarea.commentInput {
grid-column: 1;
border: 0;
padding: 0;
margin: 0;
width: 100%;
height: 40px;
min-height: 40px;
overflow: auto;
resize: none;
}
#Comments div.commentInput button {
grid-column: 2;
appearance: none;
font-size: 1.5em;
display: block;
border: 1px solid #fff;
background-color: #fff;
}
#Comments div.commentInput button:not([disabled]):hover,
#Comments div.commentInput button:not([disabled]):focus {
color: #335A87;
background-color: #ededed;
border: 1px solid #ccc;
}
#Comments div.commentInput button[disabled] {
color: rgba(51, 51, 51, 0.2);
cursor: default;
}
#Comments div.commentOutput {
height: 100%;
overflow: auto;
background-color: #fafafa;
color: #000;
}
#Comments div.commentOutput > div {
padding: 3px;
margin: 4px 6px;
border-bottom: 1px solid #ccc;
}
#Comments div.commentOutput > div span.author {
color: #444;
display: block;
font-weight: 600;
font-size: 0.95em;
float: left;
}
#Comments div.commentOutput > div span.timestamp {
display: block;
float: right;
font-size: 0.9em;
font-style: italic;
}
#Comments div.commentOutput > div div.comment {
clear: both;
display: block;
margin-left: 4px;
}
#Comments div.commentOutput > div div.comment p {
line-height: 1.2em;
padding-bottom: 0.2em;
}
#Comments div.commentOutput > div div.comment h1,
#Comments div.commentOutput > div div.comment h2,
#Comments div.commentOutput > div div.comment h3,
#Comments div.commentOutput > div div.comment h4,
#Comments div.commentOutput > div div.comment h5 {
font-family: "Segoe UI", Arial, Verdana, Tahoma, sans-serif;
font-weight: 600;
font-size: 14px;
margin: 2px 0 !important;
}
#Comments div.commentOutput > div div.comment hr {
margin-top: 0.2em;
}
#Comments div.commentOutput > div div.comment code {
font-size: 0.9em;
}
#Comments div.commentOutput > div:hover span.remove {
opacity: 0.5;
}
#Comments div.commentOutput > div span.remove {
font-size: 1.2em;
color: #e51400;
margin-left: 6px;
cursor: pointer;
opacity: 0;
}
#Comments div.commentOutput > div span.remove:hover {
opacity: 1;
}
#Comments div.commentOutput > div:last-child {
border-bottom: none;
}
#Comments.cannotAddComments {
padding-bottom: 0;
}
#Device_Show_Policies_Profile_Actions_Update_Dialog .profile-list, #Device_Show_Policies_Profile_Actions_Update_Dialog .profile-list,
#Device_Show_Policies_Batch_Actions_Update_Dialog .profile-list { #Device_Show_Policies_Batch_Actions_Update_Dialog .profile-list {
max-height: 300px; max-height: 300px;
@@ -230,8 +370,10 @@
padding-top: 0.5em; padding-top: 0.5em;
} }
#DeviceDetailTab-JobsContainer div.jobTable { #DeviceDetailTab-JobsContainer div.jobTable {
margin: -1px; min-height: 320px;
border: 1px solid #ddd; border-top: 1px solid #ccc;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
} }
#DeviceDetailTab-JobsContainer .dataTables_wrapper .dataTables_filter { #DeviceDetailTab-JobsContainer .dataTables_wrapper .dataTables_filter {
margin-top: -24px; margin-top: -24px;
+170 -2
View File
@@ -179,6 +179,172 @@
} }
} }
#DeviceDetailTab-CommentsAndJobs {
display: grid;
grid-template-columns: auto;
&.canShowComments.canShowJobs {
grid-template-columns: 375px auto;
& > #DeviceDetailTab-Comments {
grid-column: 1;
}
& > #DeviceDetailTab-JobsContainer {
grid-column: 2;
}
}
&.cannotShowComments div.jobTable {
border: 1px solid @SubtleBorderColour;
}
}
#DeviceDetailTab-CommentsContainer {
max-height: 650px;
}
#DeviceDetailTab-JobsContainer {
max-height: 650px;
overflow: auto;
}
#Comments {
box-sizing: border-box;
height: 100%;
min-height: 373px;
padding-bottom: 51px;
border: 1px solid @SubtleBorderColour;
background-color: @white;
position: relative;
div.commentInput {
border-top: 1px solid @SubtleBorderColour;
box-sizing: border-box;
width: 100%;
height: 51px;
padding: 5px;
position: absolute;
bottom: 0;
display: grid;
grid-template-columns: auto 40px;
textarea.commentInput {
grid-column: 1;
border: 0;
padding: 0;
margin: 0;
width: 100%;
height: 40px;
min-height: 40px;
overflow: auto;
resize: none;
}
button {
grid-column: 2;
appearance: none;
font-size: 1.5em;
display: block;
border: 1px solid @white;
background-color: @white;
&:not([disabled]) {
&:hover, &:focus {
color: @HyperLinkColour;
background-color: @SubtleColour;
border: 1px solid @SubtleBorderColour;
}
}
&[disabled] {
color: fade(@HeaderBackgroundColour, 20%);
cursor: default;
}
}
}
div.commentOutput {
height: 100%;
overflow: auto;
background-color: @BackgroundColourLight;
color: @black;
& > div {
padding: 3px;
margin: 4px 6px;
border-bottom: 1px solid @SubtleBorderColour;
span.author {
color: #444;
display: block;
font-weight: @FontWeightBodyBold;
font-size: 0.95em;
float: left;
}
span.timestamp {
display: block;
float: right;
font-size: 0.90em;
font-style: italic;
}
div.comment {
clear: both;
display: block;
margin-left: 4px;
p {
line-height: 1.2em;
padding-bottom: .2em;
}
h1, h2, h3, h4, h5 {
font-family: @FontFamilyBody;
font-weight: 600;
font-size: 14px;
margin: 2px 0 !important;
}
hr {
margin-top: .2em;
}
code {
font-size: .9em;
}
}
&:hover {
span.remove {
opacity: .5;
}
}
span.remove {
font-size: 1.2em;
color: @StatusRemove;
margin-left: 6px;
cursor: pointer;
opacity: 0;
&:hover {
opacity: 1;
}
}
&:last-child {
border-bottom: none;
}
}
}
&.cannotAddComments {
padding-bottom: 0;
}
}
#Device_Show_Policies_Profile_Actions_Update_Dialog, #Device_Show_Policies_Batch_Actions_Update_Dialog { #Device_Show_Policies_Profile_Actions_Update_Dialog, #Device_Show_Policies_Batch_Actions_Update_Dialog {
.profile-list { .profile-list {
max-height: 300px; max-height: 300px;
@@ -206,8 +372,10 @@
#DeviceDetailTab-JobsContainer { #DeviceDetailTab-JobsContainer {
div.jobTable { div.jobTable {
margin: -1px; min-height: 320px;
border: 1px solid #ddd; border-top: 1px solid @SubtleBorderColour;
border-right: 1px solid @SubtleBorderColour;
border-bottom: 1px solid @SubtleBorderColour;
} }
.dataTables_wrapper { .dataTables_wrapper {
File diff suppressed because one or more lines are too long
+7
View File
@@ -219,6 +219,13 @@
#UserDetailTab-CommentsAndJobs.cannotShowComments div.jobTable { #UserDetailTab-CommentsAndJobs.cannotShowComments div.jobTable {
border: 1px solid #ccc; border: 1px solid #ccc;
} }
#UserDetailTab-CommentsContainer {
max-height: 650px;
}
#UserDetailTab-JobsContainer {
max-height: 650px;
overflow: auto;
}
#Comments { #Comments {
box-sizing: border-box; box-sizing: border-box;
height: 100%; height: 100%;
+9
View File
@@ -191,6 +191,15 @@
} }
} }
#UserDetailTab-CommentsContainer {
max-height: 650px;
}
#UserDetailTab-JobsContainer {
max-height: 650px;
overflow: auto;
}
#Comments { #Comments {
box-sizing: border-box; box-sizing: border-box;
height: 100%; height: 100%;
File diff suppressed because one or more lines are too long
+22 -13
View File
@@ -909,6 +909,16 @@
</Compile> </Compile>
<Compile Include="Models\Shared\ExportFieldsModel.cs" /> <Compile Include="Models\Shared\ExportFieldsModel.cs" />
<Compile Include="Models\Shared\GenerateDocumentControlModel.cs" /> <Compile Include="Models\Shared\GenerateDocumentControlModel.cs" />
<Compile Include="Views\Device\DeviceParts\_Comments.generated.cs">
<DependentUpon>_Comments.cshtml</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Views\Device\DeviceParts\_CommentsAndJobs.generated.cs">
<DependentUpon>_CommentsAndJobs.cshtml</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Views\Device\DeviceParts\_Flags.generated.cs"> <Compile Include="Views\Device\DeviceParts\_Flags.generated.cs">
<DependentUpon>_Flags.cshtml</DependentUpon> <DependentUpon>_Flags.cshtml</DependentUpon>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@@ -1071,11 +1081,6 @@
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>_Certificates.cshtml</DependentUpon> <DependentUpon>_Certificates.cshtml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\Device\DeviceParts\_Jobs.generated.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>_Jobs.cshtml</DependentUpon>
</Compile>
<Compile Include="Views\Device\DeviceParts\_Resources.generated.cs"> <Compile Include="Views\Device\DeviceParts\_Resources.generated.cs">
<DependentUpon>_Resources.cshtml</DependentUpon> <DependentUpon>_Resources.cshtml</DependentUpon>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@@ -1336,8 +1341,8 @@
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
</Compile> </Compile>
<Compile Include="Views\User\UserParts\Comments.generated.cs"> <Compile Include="Views\User\UserParts\_Comments.generated.cs">
<DependentUpon>Comments.cshtml</DependentUpon> <DependentUpon>_Comments.cshtml</DependentUpon>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
</Compile> </Compile>
@@ -2099,6 +2104,14 @@
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>AddOffline.generated.cs</LastGenOutput> <LastGenOutput>AddOffline.generated.cs</LastGenOutput>
</None> </None>
<None Include="Views\Device\DeviceParts\_Comments.cshtml">
<Generator>RazorGenerator</Generator>
<LastGenOutput>_Comments.generated.cs</LastGenOutput>
</None>
<None Include="Views\Device\DeviceParts\_CommentsAndJobs.cshtml">
<Generator>RazorGenerator</Generator>
<LastGenOutput>_CommentsAndJobs.generated.cs</LastGenOutput>
</None>
<None Include="Views\Device\DeviceParts\_Flags.cshtml"> <None Include="Views\Device\DeviceParts\_Flags.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>_Flags.generated.cs</LastGenOutput> <LastGenOutput>_Flags.generated.cs</LastGenOutput>
@@ -2119,10 +2132,6 @@
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>_Certificates.generated.cs</LastGenOutput> <LastGenOutput>_Certificates.generated.cs</LastGenOutput>
</None> </None>
<None Include="Views\Device\DeviceParts\_Jobs.cshtml">
<Generator>RazorGenerator</Generator>
<LastGenOutput>_Jobs.generated.cs</LastGenOutput>
</None>
<None Include="Views\Device\DeviceParts\_Resources.cshtml"> <None Include="Views\Device\DeviceParts\_Resources.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>_Resources.generated.cs</LastGenOutput> <LastGenOutput>_Resources.generated.cs</LastGenOutput>
@@ -2575,9 +2584,9 @@
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>_CommentsAndJobs.generated.cs</LastGenOutput> <LastGenOutput>_CommentsAndJobs.generated.cs</LastGenOutput>
</None> </None>
<None Include="Views\User\UserParts\Comments.cshtml"> <None Include="Views\User\UserParts\_Comments.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
<LastGenOutput>Comments.generated.cs</LastGenOutput> <LastGenOutput>_Comments.generated.cs</LastGenOutput>
</None> </None>
<None Include="Views\User\UserParts\_Resources.cshtml"> <None Include="Views\User\UserParts\_Resources.cshtml">
<Generator>RazorGenerator</Generator> <Generator>RazorGenerator</Generator>
@@ -157,6 +157,30 @@ namespace Disco.Web.Areas.API.Controllers
} }
[NonAction] [NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult Comments()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Comments);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult Comment()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Comment);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult CommentAdd()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.CommentAdd);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult CommentRemove()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.CommentRemove);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult AttachmentDownload() public virtual System.Web.Mvc.ActionResult AttachmentDownload()
{ {
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.AttachmentDownload); return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.AttachmentDownload);
@@ -284,6 +308,10 @@ namespace Disco.Web.Areas.API.Controllers
public readonly string GeneratePdf = "GeneratePdf"; public readonly string GeneratePdf = "GeneratePdf";
public readonly string GeneratePdfPackage = "GeneratePdfPackage"; public readonly string GeneratePdfPackage = "GeneratePdfPackage";
public readonly string LastNetworkLogonDate = "LastNetworkLogonDate"; public readonly string LastNetworkLogonDate = "LastNetworkLogonDate";
public readonly string Comments = "Comments";
public readonly string Comment = "Comment";
public readonly string CommentAdd = "CommentAdd";
public readonly string CommentRemove = "CommentRemove";
public readonly string AttachmentDownload = "AttachmentDownload"; public readonly string AttachmentDownload = "AttachmentDownload";
public readonly string AttachmentThumbnail = "AttachmentThumbnail"; public readonly string AttachmentThumbnail = "AttachmentThumbnail";
public readonly string AttachmentUpload = "AttachmentUpload"; public readonly string AttachmentUpload = "AttachmentUpload";
@@ -322,6 +350,10 @@ namespace Disco.Web.Areas.API.Controllers
public const string GeneratePdf = "GeneratePdf"; public const string GeneratePdf = "GeneratePdf";
public const string GeneratePdfPackage = "GeneratePdfPackage"; public const string GeneratePdfPackage = "GeneratePdfPackage";
public const string LastNetworkLogonDate = "LastNetworkLogonDate"; public const string LastNetworkLogonDate = "LastNetworkLogonDate";
public const string Comments = "Comments";
public const string Comment = "Comment";
public const string CommentAdd = "CommentAdd";
public const string CommentRemove = "CommentRemove";
public const string AttachmentDownload = "AttachmentDownload"; public const string AttachmentDownload = "AttachmentDownload";
public const string AttachmentThumbnail = "AttachmentThumbnail"; public const string AttachmentThumbnail = "AttachmentThumbnail";
public const string AttachmentUpload = "AttachmentUpload"; public const string AttachmentUpload = "AttachmentUpload";
@@ -498,6 +530,39 @@ namespace Disco.Web.Areas.API.Controllers
{ {
public readonly string id = "id"; public readonly string id = "id";
} }
static readonly ActionParamsClass_Comments s_params_Comments = new ActionParamsClass_Comments();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_Comments CommentsParams { get { return s_params_Comments; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_Comments
{
public readonly string id = "id";
}
static readonly ActionParamsClass_Comment s_params_Comment = new ActionParamsClass_Comment();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_Comment CommentParams { get { return s_params_Comment; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_Comment
{
public readonly string id = "id";
}
static readonly ActionParamsClass_CommentAdd s_params_CommentAdd = new ActionParamsClass_CommentAdd();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_CommentAdd CommentAddParams { get { return s_params_CommentAdd; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_CommentAdd
{
public readonly string id = "id";
public readonly string comment = "comment";
}
static readonly ActionParamsClass_CommentRemove s_params_CommentRemove = new ActionParamsClass_CommentRemove();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_CommentRemove CommentRemoveParams { get { return s_params_CommentRemove; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_CommentRemove
{
public readonly string id = "id";
}
static readonly ActionParamsClass_AttachmentDownload s_params_AttachmentDownload = new ActionParamsClass_AttachmentDownload(); static readonly ActionParamsClass_AttachmentDownload s_params_AttachmentDownload = new ActionParamsClass_AttachmentDownload();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_AttachmentDownload AttachmentDownloadParams { get { return s_params_AttachmentDownload; } } public ActionParamsClass_AttachmentDownload AttachmentDownloadParams { get { return s_params_AttachmentDownload; } }
@@ -874,6 +939,55 @@ namespace Disco.Web.Areas.API.Controllers
return callInfo; return callInfo;
} }
[NonAction]
partial void CommentsOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string id);
[NonAction]
public override System.Web.Mvc.ActionResult Comments(string id)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Comments);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id);
CommentsOverride(callInfo, id);
return callInfo;
}
[NonAction]
partial void CommentOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id);
[NonAction]
public override System.Web.Mvc.ActionResult Comment(int id)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Comment);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id);
CommentOverride(callInfo, id);
return callInfo;
}
[NonAction]
partial void CommentAddOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string id, string comment);
[NonAction]
public override System.Web.Mvc.ActionResult CommentAdd(string id, string comment)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.CommentAdd);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "comment", comment);
CommentAddOverride(callInfo, id, comment);
return callInfo;
}
[NonAction]
partial void CommentRemoveOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id);
[NonAction]
public override System.Web.Mvc.ActionResult CommentRemove(int id)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.CommentRemove);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id);
CommentRemoveOverride(callInfo, id);
return callInfo;
}
[NonAction] [NonAction]
partial void AttachmentDownloadOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id); partial void AttachmentDownloadOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id);
@@ -217,17 +217,19 @@ namespace Disco.Web.Controllers
{ {
public readonly string _AssignmentHistory = "_AssignmentHistory"; public readonly string _AssignmentHistory = "_AssignmentHistory";
public readonly string _Certificates = "_Certificates"; public readonly string _Certificates = "_Certificates";
public readonly string _Comments = "_Comments";
public readonly string _CommentsAndJobs = "_CommentsAndJobs";
public readonly string _Details = "_Details"; public readonly string _Details = "_Details";
public readonly string _Flags = "_Flags"; public readonly string _Flags = "_Flags";
public readonly string _Jobs = "_Jobs";
public readonly string _Resources = "_Resources"; public readonly string _Resources = "_Resources";
public readonly string _Subject = "_Subject"; public readonly string _Subject = "_Subject";
} }
public readonly string _AssignmentHistory = "~/Views/Device/DeviceParts/_AssignmentHistory.cshtml"; public readonly string _AssignmentHistory = "~/Views/Device/DeviceParts/_AssignmentHistory.cshtml";
public readonly string _Certificates = "~/Views/Device/DeviceParts/_Certificates.cshtml"; public readonly string _Certificates = "~/Views/Device/DeviceParts/_Certificates.cshtml";
public readonly string _Comments = "~/Views/Device/DeviceParts/_Comments.cshtml";
public readonly string _CommentsAndJobs = "~/Views/Device/DeviceParts/_CommentsAndJobs.cshtml";
public readonly string _Details = "~/Views/Device/DeviceParts/_Details.cshtml"; public readonly string _Details = "~/Views/Device/DeviceParts/_Details.cshtml";
public readonly string _Flags = "~/Views/Device/DeviceParts/_Flags.cshtml"; public readonly string _Flags = "~/Views/Device/DeviceParts/_Flags.cshtml";
public readonly string _Jobs = "~/Views/Device/DeviceParts/_Jobs.cshtml";
public readonly string _Resources = "~/Views/Device/DeviceParts/_Resources.cshtml"; public readonly string _Resources = "~/Views/Device/DeviceParts/_Resources.cshtml";
public readonly string _Subject = "~/Views/Device/DeviceParts/_Subject.cshtml"; public readonly string _Subject = "~/Views/Device/DeviceParts/_Subject.cshtml";
} }
@@ -132,19 +132,19 @@ namespace Disco.Web.Controllers
{ {
public readonly string _AssignmentHistory = "_AssignmentHistory"; public readonly string _AssignmentHistory = "_AssignmentHistory";
public readonly string _Authorization = "_Authorization"; public readonly string _Authorization = "_Authorization";
public readonly string _Comments = "_Comments";
public readonly string _CommentsAndJobs = "_CommentsAndJobs"; public readonly string _CommentsAndJobs = "_CommentsAndJobs";
public readonly string _Flags = "_Flags"; public readonly string _Flags = "_Flags";
public readonly string _Resources = "_Resources"; public readonly string _Resources = "_Resources";
public readonly string _Subject = "_Subject"; public readonly string _Subject = "_Subject";
public readonly string Comments = "Comments";
} }
public readonly string _AssignmentHistory = "~/Views/User/UserParts/_AssignmentHistory.cshtml"; public readonly string _AssignmentHistory = "~/Views/User/UserParts/_AssignmentHistory.cshtml";
public readonly string _Authorization = "~/Views/User/UserParts/_Authorization.cshtml"; public readonly string _Authorization = "~/Views/User/UserParts/_Authorization.cshtml";
public readonly string _Comments = "~/Views/User/UserParts/_Comments.cshtml";
public readonly string _CommentsAndJobs = "~/Views/User/UserParts/_CommentsAndJobs.cshtml"; public readonly string _CommentsAndJobs = "~/Views/User/UserParts/_CommentsAndJobs.cshtml";
public readonly string _Flags = "~/Views/User/UserParts/_Flags.cshtml"; public readonly string _Flags = "~/Views/User/UserParts/_Flags.cshtml";
public readonly string _Resources = "~/Views/User/UserParts/_Resources.cshtml"; public readonly string _Resources = "~/Views/User/UserParts/_Resources.cshtml";
public readonly string _Subject = "~/Views/User/UserParts/_Subject.cshtml"; public readonly string _Subject = "~/Views/User/UserParts/_Subject.cshtml";
public readonly string Comments = "~/Views/User/UserParts/Comments.cshtml";
} }
} }
} }
@@ -0,0 +1,212 @@
@model Disco.Web.Models.Device.ShowModel
@{
Authorization.Require(Claims.Device.ShowComments);
var canAddComments = Authorization.Has(Claims.Device.Actions.AddComments);
var canRemoveAnyComments = Authorization.Has(Claims.Device.Actions.RemoveAnyComments);
var canRemoveOwnComments = Authorization.Has(Claims.Device.Actions.RemoveOwnComments);
}
<div id="Comments" class="@(canAddComments ? "canAddComments" : "cannotAddComments") @(canRemoveAnyComments ? "canRemoveAnyComments" : "cannotRemoveAnyComments") @(canRemoveOwnComments ? "canRemoveOwnComments" : "cannotRemoveOwnComments")" data-id="@Model.Device.SerialNumber" data-userid="@CurrentUser.UserId" data-addurl="@Url.Action(MVC.API.Device.CommentAdd(Model.Device.SerialNumber))" data-removeurl="@Url.Action(MVC.API.Device.CommentRemove())" data-geturl="@Url.Action(MVC.API.Device.Comment())">
@Html.AntiForgeryToken()
@if (canAddComments)
{
<div class="commentInput">
<textarea class="commentInput" placeholder="add comment..." accesskey="l"></textarea>
<button type="button" title="Add Comment" disabled><i class="fa fa-comment"></i></button>
</div>
}
<div class="commentOutput">
@foreach (var c in Model.Device.DeviceComments.OrderBy(m => m.Timestamp))
{
<div class="comment" data-commentid="@c.Id">
<span class="author">@c.TechUser.ToStringFriendly()</span>@if (canRemoveAnyComments || (canRemoveOwnComments && c.TechUserId.Equals(CurrentUser.UserId, StringComparison.OrdinalIgnoreCase)))
{<text><span class="remove fa fa-times-circle"></span></text>}<span class="timestamp" data-livestamp="@(c.Timestamp.ToUnixEpoc())" title="@c.Timestamp.ToFullDateTime()">@c.Timestamp.ToFullDateTime()</span>
<div class="comment">@c.Comments.ToHtmlComment()</div>
</div>
}
</div>
</div>
<script>
if (!document.DiscoFunctions) {
document.DiscoFunctions = {};
}
$(function () {
const $comments = $('#Comments');
const $commentOutput = $comments.find('.commentOutput');
window.setTimeout(function () {
$commentOutput[0].scrollTop = $commentOutput[0].scrollHeight; // Scroll to Bottom
}, 0);
$('#DeviceDetailTabs').on('tabsactivate', function (event, ui) {
if (ui.newPanel && ui.newPanel.is('#DeviceDetailTab-CommentsAndJobs')) {
$commentOutput[0].scrollTop = $commentOutput[0].scrollHeight; // Scroll to Bottom
}
});
function onCommentAdded(id) {
onCommentAddedAsync(id);
}
async function onCommentAddedAsync(id) {
const formData = new FormData();
formData.append('__RequestVerificationToken', $comments.find('input[name="__RequestVerificationToken"]').val());
formData.append('id', id);
const response = await fetch($comments.attr('data-geturl'), {
method: 'POST',
body: formData
});
if (!response.ok) {
alert('Unable to load live comment ' + id + ': ' + response.statusText);
} else {
const comment = await response.json();
if ($comments.hasClass('canRemoveAnyComments'))
renderComment(comment, false, true);
else if ($comments.hasClass('canRemoveOwnComments'))
renderComment(comment, false, (comment.AuthorId === $comments.attr('data-userid')));
else
renderComment(comment, false, false);
}
}
function onCommentRemoved(id) {
$commentOutput.children('div[data-commentid="' + id + '"]').slideUp(300).delay(300).queue(function () {
const $this = $(this);
$this.find('.timestamp').livestamp('destroy');
$this.remove();
});
}
function renderComment(c, quick, canRemove) {
let t = '<div><span class="author" />';
if (canRemove)
t += '<span class="remove fa fa-times-circle" />';
t += '<span class="timestamp" /><div class="comment" /></div>';
const e = $(t);
e.attr('data-commentid', c.Id);
e.find('.author').text(c.Author);
e.find('.timestamp').text(c.TimestampFull).attr('title', c.TimestampFull).livestamp(c.TimestampUnixEpoc);
e.find('.comment').html(c.HtmlComments);
$commentOutput.append(e);
if (!quick) {
e.animate({ backgroundColor: '#ffff99' }, 500, function () {
e.animate({ backgroundColor: '#fafafa' }, 500, function () {
e.css('background-color', '');
});
});
$commentOutput.animate({ scrollTop: $commentOutput[0].scrollHeight }, 250)
}
}
document.DiscoFunctions.onCommentAdded = onCommentAdded;
document.DiscoFunctions.onCommentRemoved = onCommentRemoved;
});
</script>
@if (canAddComments)
{
<script>
$(function () {
const $comments = $('#Comments');
const $commentInput = $comments.find('textarea.commentInput');
const $commentInputButton = $comments.find('button');
$commentInputButton.on('click', postComment);
$commentInput.on('keypress', function (e) {
if (e.which == 13 && !e.shiftKey) {
postComment();
return false;
}
});
async function postComment() {
if ($commentInputButton.prop('disabled')) {
alert('Disconnected from the Disco ICT Server, please refresh this page and try again');
return;
}
const comment = $commentInput.val();
if (comment == '') {
alert('Enter a comment to post');
$commentInput.focus();
return;
}
$commentInput.prop('disabled', true);
const formData = new FormData();
formData.append('__RequestVerificationToken', $comments.find('input[name="__RequestVerificationToken"]').val());
formData.append('comment', comment);
const response = await fetch($comments.attr('data-addurl'), {
method: 'POST',
body: formData
});
if (response.ok) {
$commentInput.val('').prop('disabled', false).focus();
} else {
alert('Unable to add comment: ' + response.statusText);
$commentInput.prop('disabled', false).focus();
}
}
});
</script>
}
@if (canRemoveAnyComments || canRemoveOwnComments)
{
<script>
$(function () {
const $comments = $('#Comments');
const $commentOutput = $comments.find('.commentOutput');
let $dialogRemove = null;
$commentOutput.on('click', 'span.remove', removeComment);
function removeComment(e) {
e.preventDefault();
const commentId = $(this).closest('div').attr('data-commentid');
if (!$dialogRemove) {
$dialogRemove = $('<div class="dialog" title="Remove this Comment?"><p><i class="fa fa-exclamation-triangle fa-lg"></i>&nbsp;Are you sure?</p></div>')
.appendTo(document.body)
.dialog({
resizable: false,
height: 140,
modal: true,
autoOpen: false
});
}
$dialogRemove.dialog("enable").dialog('option', 'buttons', {
"Remove": function () {
$dialogRemove.dialog("disable");
$dialogRemove.dialog("option", "buttons", null);
removeCommentAsync(commentId);
},
"Cancel": function () {
$dialogRemove.dialog("close");
}
}).dialog('open');
}
async function removeCommentAsync(commentId) {
const formData = new FormData();
formData.append('__RequestVerificationToken', $comments.find('input[name="__RequestVerificationToken"]').val());
formData.append('id', commentId);
const response = await fetch($comments.attr('data-removeurl'), {
method: 'POST',
body: formData
});
if (!response.ok) {
alert('Unable to remove comment: ' + response.statusText);
}
$dialogRemove.dialog("close");
}
});
</script>
}
@@ -0,0 +1,452 @@
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Disco.Web.Views.Device.DeviceParts
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Web.Security;
using System.Web.UI;
using System.Web.WebPages;
using Disco;
using Disco.Models.Repository;
using Disco.Services;
using Disco.Services.Authorization;
using Disco.Services.Web;
using Disco.Web;
using Disco.Web.Extensions;
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")]
[System.Web.WebPages.PageVirtualPathAttribute("~/Views/Device/DeviceParts/_Comments.cshtml")]
public partial class _Comments : Disco.Services.Web.WebViewPage<Disco.Web.Models.Device.ShowModel>
{
public _Comments()
{
}
public override void Execute()
{
#line 2 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Authorization.Require(Claims.Device.ShowComments);
var canAddComments = Authorization.Has(Claims.Device.Actions.AddComments);
var canRemoveAnyComments = Authorization.Has(Claims.Device.Actions.RemoveAnyComments);
var canRemoveOwnComments = Authorization.Has(Claims.Device.Actions.RemoveOwnComments);
#line default
#line hidden
WriteLiteral("\r\n<div");
WriteLiteral(" id=\"Comments\"");
WriteAttribute("class", Tuple.Create(" class=\"", 387), Tuple.Create("\"", 607)
#line 8 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
, Tuple.Create(Tuple.Create("", 395), Tuple.Create<System.Object, System.Int32>(canAddComments ? "canAddComments" : "cannotAddComments"
#line default
#line hidden
, 395), false)
#line 8 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
, Tuple.Create(Tuple.Create(" ", 453), Tuple.Create<System.Object, System.Int32>(canRemoveAnyComments ? "canRemoveAnyComments" : "cannotRemoveAnyComments"
#line default
#line hidden
, 454), false)
#line 8 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
, Tuple.Create(Tuple.Create(" ", 530), Tuple.Create<System.Object, System.Int32>(canRemoveOwnComments ? "canRemoveOwnComments" : "cannotRemoveOwnComments"
#line default
#line hidden
, 531), false)
);
WriteLiteral(" data-id=\"");
#line 8 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(Model.Device.SerialNumber);
#line default
#line hidden
WriteLiteral("\"");
WriteLiteral(" data-userid=\"");
#line 8 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(CurrentUser.UserId);
#line default
#line hidden
WriteLiteral("\"");
WriteLiteral(" data-addurl=\"");
#line 8 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(Url.Action(MVC.API.Device.CommentAdd(Model.Device.SerialNumber)));
#line default
#line hidden
WriteLiteral("\"");
WriteLiteral(" data-removeurl=\"");
#line 8 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(Url.Action(MVC.API.Device.CommentRemove()));
#line default
#line hidden
WriteLiteral("\"");
WriteLiteral(" data-geturl=\"");
#line 8 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(Url.Action(MVC.API.Device.Comment()));
#line default
#line hidden
WriteLiteral("\"");
WriteLiteral(">\r\n");
WriteLiteral(" ");
#line 9 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(Html.AntiForgeryToken());
#line default
#line hidden
WriteLiteral("\r\n");
#line 10 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
#line default
#line hidden
#line 10 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
if (canAddComments)
{
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" class=\"commentInput\"");
WriteLiteral(">\r\n <textarea");
WriteLiteral(" class=\"commentInput\"");
WriteLiteral(" placeholder=\"add comment...\"");
WriteLiteral(" accesskey=\"l\"");
WriteLiteral("></textarea>\r\n <button");
WriteLiteral(" type=\"button\"");
WriteLiteral(" title=\"Add Comment\"");
WriteLiteral(" disabled><i");
WriteLiteral(" class=\"fa fa-comment\"");
WriteLiteral("></i></button>\r\n </div>\r\n");
#line 16 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
}
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" class=\"commentOutput\"");
WriteLiteral(">\r\n");
#line 18 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
#line default
#line hidden
#line 18 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
foreach (var c in Model.Device.DeviceComments.OrderBy(m => m.Timestamp))
{
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" class=\"comment\"");
WriteLiteral(" data-commentid=\"");
#line 20 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(c.Id);
#line default
#line hidden
WriteLiteral("\"");
WriteLiteral(">\r\n <span");
WriteLiteral(" class=\"author\"");
WriteLiteral(">");
#line 21 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(c.TechUser.ToStringFriendly());
#line default
#line hidden
WriteLiteral("</span>");
#line 21 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
if (canRemoveAnyComments || (canRemoveOwnComments && c.TechUserId.Equals(CurrentUser.UserId, StringComparison.OrdinalIgnoreCase)))
{
#line default
#line hidden
WriteLiteral("<span");
WriteLiteral(" class=\"remove fa fa-times-circle\"");
WriteLiteral("></span>");
#line 22 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
}
#line default
#line hidden
WriteLiteral("<span");
WriteLiteral(" class=\"timestamp\"");
WriteLiteral(" data-livestamp=\"");
#line 22 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(c.Timestamp.ToUnixEpoc());
#line default
#line hidden
WriteLiteral("\"");
WriteAttribute("title", Tuple.Create(" title=\"", 1737), Tuple.Create("\"", 1774)
#line 22 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
, Tuple.Create(Tuple.Create("", 1745), Tuple.Create<System.Object, System.Int32>(c.Timestamp.ToFullDateTime()
#line default
#line hidden
, 1745), false)
);
WriteLiteral(">");
#line 22 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(c.Timestamp.ToFullDateTime());
#line default
#line hidden
WriteLiteral("</span>\r\n <div");
WriteLiteral(" class=\"comment\"");
WriteLiteral(">");
#line 23 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
Write(c.Comments.ToHtmlComment());
#line default
#line hidden
WriteLiteral("</div>\r\n </div>\r\n");
#line 25 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
}
#line default
#line hidden
WriteLiteral(" </div>\r\n</div>\r\n<script>\r\n if (!document.DiscoFunctions) {\r\n docume" +
"nt.DiscoFunctions = {};\r\n }\r\n\r\n $(function () {\r\n const $comments =" +
" $(\'#Comments\');\r\n const $commentOutput = $comments.find(\'.commentOutput\'" +
");\r\n\r\n window.setTimeout(function () {\r\n $commentOutput[0].scr" +
"ollTop = $commentOutput[0].scrollHeight; // Scroll to Bottom\r\n }, 0);\r\n " +
" $(\'#DeviceDetailTabs\').on(\'tabsactivate\', function (event, ui) {\r\n " +
" if (ui.newPanel && ui.newPanel.is(\'#DeviceDetailTab-CommentsAndJobs\')) {\r\n " +
" $commentOutput[0].scrollTop = $commentOutput[0].scrollHeight; // S" +
"croll to Bottom\r\n }\r\n });\r\n\r\n function onCommentAdded(i" +
"d) {\r\n onCommentAddedAsync(id);\r\n }\r\n async function on" +
"CommentAddedAsync(id) {\r\n const formData = new FormData();\r\n " +
" formData.append(\'__RequestVerificationToken\', $comments.find(\'input[name=\"__R" +
"equestVerificationToken\"]\').val());\r\n formData.append(\'id\', id);\r\n\r\n " +
" const response = await fetch($comments.attr(\'data-geturl\'), {\r\n " +
" method: \'POST\',\r\n body: formData\r\n });\r\n\r\n " +
" if (!response.ok) {\r\n alert(\'Unable to load live commen" +
"t \' + id + \': \' + response.statusText);\r\n } else {\r\n c" +
"onst comment = await response.json();\r\n\r\n if ($comments.hasClass(" +
"\'canRemoveAnyComments\'))\r\n renderComment(comment, false, true" +
");\r\n else if ($comments.hasClass(\'canRemoveOwnComments\'))\r\n " +
" renderComment(comment, false, (comment.AuthorId === $comments.attr" +
"(\'data-userid\')));\r\n else\r\n renderComment(comm" +
"ent, false, false);\r\n }\r\n }\r\n function onCommentRemoved" +
"(id) {\r\n $commentOutput.children(\'div[data-commentid=\"\' + id + \'\"]\')." +
"slideUp(300).delay(300).queue(function () {\r\n const $this = $(thi" +
"s);\r\n $this.find(\'.timestamp\').livestamp(\'destroy\');\r\n " +
" $this.remove();\r\n });\r\n }\r\n function renderComment" +
"(c, quick, canRemove) {\r\n let t = \'<div><span class=\"author\" />\';\r\n " +
" if (canRemove)\r\n t += \'<span class=\"remove fa fa-times-" +
"circle\" />\';\r\n t += \'<span class=\"timestamp\" /><div class=\"comment\" /" +
"></div>\';\r\n\r\n const e = $(t);\r\n e.attr(\'data-commentid\', c" +
".Id);\r\n e.find(\'.author\').text(c.Author);\r\n e.find(\'.times" +
"tamp\').text(c.TimestampFull).attr(\'title\', c.TimestampFull).livestamp(c.Timestam" +
"pUnixEpoc);\r\n e.find(\'.comment\').html(c.HtmlComments);\r\n\r\n " +
" $commentOutput.append(e);\r\n\r\n if (!quick) {\r\n e.anima" +
"te({ backgroundColor: \'#ffff99\' }, 500, function () {\r\n e.ani" +
"mate({ backgroundColor: \'#fafafa\' }, 500, function () {\r\n " +
" e.css(\'background-color\', \'\');\r\n });\r\n });\r\n " +
" $commentOutput.animate({ scrollTop: $commentOutput[0].scrollHeigh" +
"t }, 250)\r\n }\r\n }\r\n\r\n document.DiscoFunctions.onComment" +
"Added = onCommentAdded;\r\n document.DiscoFunctions.onCommentRemoved = onCo" +
"mmentRemoved;\r\n });\r\n</script>\r\n");
#line 107 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
if (canAddComments)
{
#line default
#line hidden
WriteLiteral(" <script>\r\n $(function () {\r\n const $comments = $(\'#Comments" +
"\');\r\n const $commentInput = $comments.find(\'textarea.commentInput\');\r" +
"\n const $commentInputButton = $comments.find(\'button\');\r\n " +
"$commentInputButton.on(\'click\', postComment);\r\n $commentInput.on(\'key" +
"press\', function (e) {\r\n if (e.which == 13 && !e.shiftKey) {\r\n " +
" postComment();\r\n return false;\r\n " +
" }\r\n });\r\n\r\n async function postComment() {\r\n " +
" if ($commentInputButton.prop(\'disabled\')) {\r\n alert(\'Di" +
"sconnected from the Disco ICT Server, please refresh this page and try again\');\r" +
"\n return;\r\n }\r\n\r\n const comment" +
" = $commentInput.val();\r\n\r\n if (comment == \'\') {\r\n " +
" alert(\'Enter a comment to post\');\r\n $commentInput.focus(" +
");\r\n return;\r\n }\r\n\r\n $commentIn" +
"put.prop(\'disabled\', true);\r\n\r\n const formData = new FormData();\r" +
"\n formData.append(\'__RequestVerificationToken\', $comments.find(\'i" +
"nput[name=\"__RequestVerificationToken\"]\').val());\r\n formData.appe" +
"nd(\'comment\', comment);\r\n\r\n const response = await fetch($comment" +
"s.attr(\'data-addurl\'), {\r\n method: \'POST\',\r\n " +
" body: formData\r\n });\r\n\r\n if (response.ok) {\r\n " +
" $commentInput.val(\'\').prop(\'disabled\', false).focus();\r\n " +
" } else {\r\n alert(\'Unable to add comment: \' + respon" +
"se.statusText);\r\n $commentInput.prop(\'disabled\', false).focus" +
"();\r\n }\r\n }\r\n });\r\n </script>\r\n");
#line 156 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
}
#line default
#line hidden
#line 157 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
if (canRemoveAnyComments || canRemoveOwnComments)
{
#line default
#line hidden
WriteLiteral(" <script>\r\n $(function () {\r\n const $comments = $(\'#Comments" +
"\');\r\n const $commentOutput = $comments.find(\'.commentOutput\');\r\n " +
" let $dialogRemove = null;\r\n\r\n $commentOutput.on(\'click\', \'span" +
".remove\', removeComment);\r\n\r\n function removeComment(e) {\r\n " +
" e.preventDefault();\r\n\r\n const commentId = $(this).closest(\'" +
"div\').attr(\'data-commentid\');\r\n\r\n if (!$dialogRemove) {\r\n " +
" $dialogRemove = $(\'<div class=\"dialog\" title=\"Remove this Comment?\">" +
"<p><i class=\"fa fa-exclamation-triangle fa-lg\"></i>&nbsp;Are you sure?</p></div>" +
"\')\r\n .appendTo(document.body)\r\n .d" +
"ialog({\r\n resizable: false,\r\n " +
" height: 140,\r\n modal: true,\r\n " +
" autoOpen: false\r\n });\r\n }\r\n\r\n " +
" $dialogRemove.dialog(\"enable\").dialog(\'option\', \'buttons\', {\r\n " +
" \"Remove\": function () {\r\n $dialogRemove.dial" +
"og(\"disable\");\r\n $dialogRemove.dialog(\"option\", \"buttons\"" +
", null);\r\n\r\n removeCommentAsync(commentId);\r\n " +
" },\r\n \"Cancel\": function () {\r\n " +
" $dialogRemove.dialog(\"close\");\r\n }\r\n }).dialo" +
"g(\'open\');\r\n }\r\n async function removeCommentAsync(comment" +
"Id) {\r\n const formData = new FormData();\r\n formDat" +
"a.append(\'__RequestVerificationToken\', $comments.find(\'input[name=\"__RequestVeri" +
"ficationToken\"]\').val());\r\n formData.append(\'id\', commentId);\r\n\r\n" +
" const response = await fetch($comments.attr(\'data-removeurl\'), {" +
"\r\n method: \'POST\',\r\n body: formData\r\n " +
" });\r\n\r\n if (!response.ok) {\r\n alert" +
"(\'Unable to remove comment: \' + response.statusText);\r\n }\r\n " +
" $dialogRemove.dialog(\"close\");\r\n }\r\n });\r\n </scri" +
"pt>\r\n");
#line 212 "..\..\Views\Device\DeviceParts\_Comments.cshtml"
}
#line default
#line hidden
}
}
}
#pragma warning restore 1591
@@ -0,0 +1,41 @@
@model Disco.Web.Models.Device.ShowModel
@{
var canShowComments = Authorization.Has(Claims.Device.ShowComments);
var canShowJobs = Authorization.Has(Claims.Device.ShowJobs);
var jobCount = (Model.Device.Jobs == null ? 0 : Model.Device.Jobs.Count).ToString();
string label;
if (canShowComments & canShowJobs)
{
label = "Comments and Jobs [" + jobCount + "]";
}
else if (canShowComments)
{
label = "Comments";
}
else if (canShowJobs)
{
label = "Jobs [" + jobCount + "]";
}
else
{
return;
}
}
<div id="DeviceDetailTab-CommentsAndJobs" class="DevicePart @(canShowComments ? "canShowComments" : "cannotShowComments") @(canShowJobs ? "canShowJobs" : "cannotShowJobs")">
@if (canShowComments)
{
<div id="DeviceDetailTab-CommentsContainer">
@Html.Partial(MVC.Device.Views.DeviceParts._Comments, Model)
</div>
}
@if (canShowJobs)
{
<div id="DeviceDetailTab-JobsContainer">
@Html.Partial(MVC.Shared.Views._JobTable, Model.Jobs)
</div>
}
<script>
$('#DeviceDetailTabItems').append('<li><a href="#DeviceDetailTab-CommentsAndJobs">@label</a></li>');
</script>
</div>
@@ -0,0 +1,185 @@
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Disco.Web.Views.Device.DeviceParts
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Web.Security;
using System.Web.UI;
using System.Web.WebPages;
using Disco;
using Disco.Models.Repository;
using Disco.Services;
using Disco.Services.Authorization;
using Disco.Services.Web;
using Disco.Web;
using Disco.Web.Extensions;
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")]
[System.Web.WebPages.PageVirtualPathAttribute("~/Views/Device/DeviceParts/_CommentsAndJobs.cshtml")]
public partial class _CommentsAndJobs : Disco.Services.Web.WebViewPage<Disco.Web.Models.Device.ShowModel>
{
public _CommentsAndJobs()
{
}
public override void Execute()
{
#line 2 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
var canShowComments = Authorization.Has(Claims.Device.ShowComments);
var canShowJobs = Authorization.Has(Claims.Device.ShowJobs);
var jobCount = (Model.Device.Jobs == null ? 0 : Model.Device.Jobs.Count).ToString();
string label;
if (canShowComments & canShowJobs)
{
label = "Comments and Jobs [" + jobCount + "]";
}
else if (canShowComments)
{
label = "Comments";
}
else if (canShowJobs)
{
label = "Jobs [" + jobCount + "]";
}
else
{
return;
}
#line default
#line hidden
WriteLiteral("\r\n<div");
WriteLiteral(" id=\"DeviceDetailTab-CommentsAndJobs\"");
WriteAttribute("class", Tuple.Create(" class=\"", 652), Tuple.Create("\"", 782)
, Tuple.Create(Tuple.Create("", 660), Tuple.Create("DevicePart", 660), true)
#line 25 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
, Tuple.Create(Tuple.Create(" ", 670), Tuple.Create<System.Object, System.Int32>(canShowComments ? "canShowComments" : "cannotShowComments"
#line default
#line hidden
, 671), false)
#line 25 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
, Tuple.Create(Tuple.Create(" ", 732), Tuple.Create<System.Object, System.Int32>(canShowJobs ? "canShowJobs" : "cannotShowJobs"
#line default
#line hidden
, 733), false)
);
WriteLiteral(">\r\n");
#line 26 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
#line default
#line hidden
#line 26 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
if (canShowComments)
{
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" id=\"DeviceDetailTab-CommentsContainer\"");
WriteLiteral(">\r\n");
WriteLiteral(" ");
#line 29 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Comments, Model));
#line default
#line hidden
WriteLiteral("\r\n </div>\r\n");
#line 31 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
}
#line default
#line hidden
WriteLiteral(" ");
#line 32 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
if (canShowJobs)
{
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" id=\"DeviceDetailTab-JobsContainer\"");
WriteLiteral(">\r\n");
WriteLiteral(" ");
#line 35 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
Write(Html.Partial(MVC.Shared.Views._JobTable, Model.Jobs));
#line default
#line hidden
WriteLiteral("\r\n </div>\r\n");
#line 37 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
}
#line default
#line hidden
WriteLiteral(" <script>\r\n $(\'#DeviceDetailTabItems\').append(\'<li><a href=\"#DeviceDeta" +
"ilTab-CommentsAndJobs\">");
#line 39 "..\..\Views\Device\DeviceParts\_CommentsAndJobs.cshtml"
Write(label);
#line default
#line hidden
WriteLiteral("</a></li>\');\r\n </script>\r\n</div>\r\n");
}
}
}
#pragma warning restore 1591
@@ -1,12 +0,0 @@
@model Disco.Web.Models.Device.ShowModel
@{
Authorization.Require(Claims.Device.ShowJobs);
}
<div id="DeviceDetailTab-Jobs" class="DevicePart">
<div id="DeviceDetailTab-JobsContainer">
@Html.Partial(MVC.Shared.Views._JobTable, Model.Jobs)
</div>
<script>
$('#DeviceDetailTabItems').append('<li><a href="#DeviceDetailTab-Jobs">Jobs [@(Model.Jobs.Items.Count())]</a></li>');
</script>
</div>
@@ -1,90 +0,0 @@
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Disco.Web.Views.Device.DeviceParts
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Web.Security;
using System.Web.UI;
using System.Web.WebPages;
using Disco;
using Disco.Models.Repository;
using Disco.Services;
using Disco.Services.Authorization;
using Disco.Services.Web;
using Disco.Web;
using Disco.Web.Extensions;
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")]
[System.Web.WebPages.PageVirtualPathAttribute("~/Views/Device/DeviceParts/_Jobs.cshtml")]
public partial class _Jobs : Disco.Services.Web.WebViewPage<Disco.Web.Models.Device.ShowModel>
{
public _Jobs()
{
}
public override void Execute()
{
#line 2 "..\..\Views\Device\DeviceParts\_Jobs.cshtml"
Authorization.Require(Claims.Device.ShowJobs);
#line default
#line hidden
WriteLiteral("\r\n<div");
WriteLiteral(" id=\"DeviceDetailTab-Jobs\"");
WriteLiteral(" class=\"DevicePart\"");
WriteLiteral(">\r\n <div");
WriteLiteral(" id=\"DeviceDetailTab-JobsContainer\"");
WriteLiteral(">\r\n");
WriteLiteral(" ");
#line 7 "..\..\Views\Device\DeviceParts\_Jobs.cshtml"
Write(Html.Partial(MVC.Shared.Views._JobTable, Model.Jobs));
#line default
#line hidden
WriteLiteral("\r\n </div>\r\n <script>\r\n $(\'#DeviceDetailTabItems\').append(\'<li><a hre" +
"f=\"#DeviceDetailTab-Jobs\">Jobs [");
#line 10 "..\..\Views\Device\DeviceParts\_Jobs.cshtml"
Write(Model.Jobs.Items.Count());
#line default
#line hidden
WriteLiteral("]</a></li>\');\r\n </script>\r\n</div>\r\n");
}
}
}
#pragma warning restore 1591
@@ -8,7 +8,6 @@
Html.BundleDeferred("~/Style/Shadowbox"); Html.BundleDeferred("~/Style/Shadowbox");
Html.BundleDeferred("~/ClientScripts/Modules/Shadowbox"); Html.BundleDeferred("~/ClientScripts/Modules/Shadowbox");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
if (canAddAttachments) if (canAddAttachments)
{ {
@@ -29,17 +28,18 @@
{ {
foreach (var da in Model.Device.DeviceAttachments.OrderByDescending(a => a.Id)) foreach (var da in Model.Device.DeviceAttachments.OrderByDescending(a => a.Id))
{ {
<a href="@Url.Action(MVC.API.Device.AttachmentDownload(da.Id))" data-attachmentid="@da.Id" data-mimetype="@da.MimeType"> <a href="@Url.Action(MVC.API.Device.AttachmentDownload(da.Id))" data-attachmentid="@da.Id" data-mimetype="@da.MimeType">
<span class="icon" title="@da.Filename"> <span class="icon" title="@da.Filename">
<img alt="Attachment Thumbnail" src="@(Url.Action(MVC.API.Device.AttachmentThumbnail(da.Id)))" /></span> <img alt="Attachment Thumbnail" src="@(Url.Action(MVC.API.Device.AttachmentThumbnail(da.Id)))" />
<span class="comments" title="@(da.Comments ?? da.Filename)"> </span>
@{if (!string.IsNullOrEmpty(da.DocumentTemplateId)) <span class="comments" title="@(da.Comments ?? da.Filename)">
{ @da.DocumentTemplate.Description} @{if (!string.IsNullOrEmpty(da.DocumentTemplateId))
else { @da.DocumentTemplate.Description}
{ @(da.Comments ?? da.Filename) }} else
</span><span class="author">@da.TechUser.ToString()</span>@if (canRemoveAnyAttachments || (canRemoveOwnAttachments && da.TechUserId.Equals(CurrentUser.UserId, StringComparison.OrdinalIgnoreCase))) { @(da.Comments ?? da.Filename) }}
{<text><span class="remove fa fa-times-circle"></span></text>}<span class="timestamp" title="@da.Timestamp.ToFullDateTime()" data-livestamp="@da.Timestamp.ToUnixEpoc()">@da.Timestamp.ToFullDateTime()</span> </span><span class="author">@da.TechUser.ToString()</span>@if (canRemoveAnyAttachments || (canRemoveOwnAttachments && da.TechUserId.Equals(CurrentUser.UserId, StringComparison.OrdinalIgnoreCase)))
</a> {<text><span class="remove fa fa-times-circle"></span></text>}<span class="timestamp" title="@da.Timestamp.ToFullDateTime()" data-livestamp="@da.Timestamp.ToUnixEpoc()">@da.Timestamp.ToFullDateTime()</span>
</a>
} }
} }
</div> </div>
@@ -56,63 +56,12 @@
modal: true modal: true
}); });
$(function () { $(function () {
var $Attachments = $('#Attachments'); const $Attachments = $('#Attachments');
var $attachmentOutput = $Attachments.find('.attachmentOutput'); const $attachmentOutput = $Attachments.find('.attachmentOutput');
var $attachmentDownloadHost; let $attachmentDownloadHost = null;
let $dialogRemoveAttachment = null;
var $dialogRemoveAttachment = null; function onAttachmentAdded(id, quick) {
// Connect to Hub
var hub = $.connection.deviceUpdates;
// Map Functions
hub.client.addAttachment = onAddAttachment;
hub.client.removeAttachment = onRemoveAttachment;
$.connection.hub.qs = { DeviceSerialNumber: '@(Model.Device.SerialNumber)' };
$.connection.hub.error(onHubFailed);
$.connection.hub.disconnected(onHubFailed);
$.connection.hub.reconnecting(function () {
$('#AttachmentsContainer').find('span.action.enabled').addClass('disabled');
});
$.connection.hub.reconnected(function () {
$('#AttachmentsContainer').find('span.action.enabled').removeClass('disabled');
});
// Start Connection
$.connection.hub.start(function () {
$('#AttachmentsContainer').find('span.action.enabled').removeClass('disabled');
}).fail(onHubFailed);
function onHubFailed(error) {
// Disable UI
$('#AttachmentsContainer').find('span.action.enabled').addClass('disabled');
// Show Dialog Message
if ($('.disconnected-dialog').length == 0) {
$('<div>')
.addClass('dialog disconnected-dialog')
.html('<h3><span class="fa-stack fa-lg"><i class="fa fa-wifi fa-stack-1x"></i><i class="fa fa-ban fa-stack-2x error"></i></span>Disconnected from the Disco ICT Server</h3><div>This page is not receiving live updates. Please ensure you are connected to the server, then refresh this page to enable features.</div>')
.dialog({
resizable: false,
title: 'Disconnected',
width: 400,
modal: true,
buttons: {
'Refresh Now': function () {
$(this).dialog('option', 'buttons', null);
window.location.reload(true);
},
'Close': function () {
$(this).dialog('destroy');
}
}
});
}
}
function onAddAttachment(id, quick) {
var data = { id: id }; var data = { id: id };
$.ajax({ $.ajax({
url: '@Url.Action(MVC.API.Device.Attachment())', url: '@Url.Action(MVC.API.Device.Attachment())',
@@ -185,25 +134,12 @@
buildThumbnail(); buildThumbnail();
} }
function onRemoveAttachment(id) {
var a = $attachmentOutput.find('a[data-attachmentid=' + id + ']');
a.hide(300).delay(300).queue(function () {
var $this = $(this);
if ($this.attr('data-mimetype').toLowerCase().indexOf('image/') == 0)
Shadowbox.removeCache(this);
$this.find('.timestamp').livestamp('destroy');
$this.remove();
onUpdate();
});
}
function onDownload() { function onDownload() {
var $this = $(this); var $this = $(this);
var url = $this.attr('href'); var url = $this.attr('href');
if ($.connection && $.connection.hub && $.connection.hub.transport && if ($.connection && $.connection.hub && $.connection.hub.transport &&
$.connection.hub.transport.name == 'foreverFrame') { $.connection.hub.transport.name == 'foreverFrame') {
// SignalR active with foreverFrame transport - use popup window // SignalR active with foreverFrame transport - use popup window
window.open(url, '_blank', 'height=150,width=250,location=no,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no'); window.open(url, '_blank', 'height=150,width=250,location=no,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no');
} else { } else {
@@ -222,12 +158,28 @@
return false; return false;
} }
function onAttachmentRemoved(id) {
var a = $attachmentOutput.find('a[data-attachmentid=' + id + ']');
a.hide(300).delay(300).queue(function () {
var $this = $(this);
if ($this.attr('data-mimetype').toLowerCase().indexOf('image/') == 0)
Shadowbox.removeCache(this);
$this.find('.timestamp').livestamp('destroy');
$this.remove();
onUpdate();
});
}
function onUpdate() { function onUpdate() {
var attachmentCount = $attachmentOutput.children('a').length; var attachmentCount = $attachmentOutput.children('a').length;
var tabHeading = 'Attachments [' + attachmentCount + ']'; var tabHeading = 'Attachments [' + attachmentCount + ']';
$('#DeviceDetailTab-ResourcesLink').text(tabHeading); $('#DeviceDetailTab-ResourcesLink').text(tabHeading);
} }
document.DiscoFunctions.onAttachmentAdded = onAttachmentAdded;
document.DiscoFunctions.onAttachmentRemoved = onAttachmentRemoved;
@if (canAddAttachments) @if (canAddAttachments)
{<text> {<text>
//#region Add Attachments //#region Add Attachments
@@ -54,7 +54,6 @@ namespace Disco.Web.Views.Device.DeviceParts
Html.BundleDeferred("~/Style/Shadowbox"); Html.BundleDeferred("~/Style/Shadowbox");
Html.BundleDeferred("~/ClientScripts/Modules/Shadowbox"); Html.BundleDeferred("~/ClientScripts/Modules/Shadowbox");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
if (canAddAttachments) if (canAddAttachments)
{ {
@@ -82,21 +81,46 @@ WriteLiteral(">\r\n <div");
WriteLiteral(" id=\"Attachments\""); WriteLiteral(" id=\"Attachments\"");
WriteAttribute("class", Tuple.Create(" class=\"", 888), Tuple.Create("\"", 963) WriteAttribute("class", Tuple.Create(" class=\"", 820), Tuple.Create("\"", 1067)
#line 22 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 21 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
, Tuple.Create(Tuple.Create("", 896), Tuple.Create<System.Object, System.Int32>(canAddAttachments ? "canAddAttachments" : "cannotAddAttachments" , Tuple.Create(Tuple.Create("", 828), Tuple.Create<System.Object, System.Int32>(canAddAttachments ? "canAddAttachments" : "cannotAddAttachments"
#line default
#line hidden
, 828), false)
#line 21 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
, Tuple.Create(Tuple.Create(" ", 895), Tuple.Create<System.Object, System.Int32>(canRemoveAnyAttachments ? "canRemoveAnyAttachments" : "cannotRemoveAnyAttachments"
#line default #line default
#line hidden #line hidden
, 896), false) , 896), false)
#line 21 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
, Tuple.Create(Tuple.Create(" ", 981), Tuple.Create<System.Object, System.Int32>(canRemoveOwnAttachments ? "canRemoveOwnAttachments" : "cannotRemoveOwnAttachments"
#line default
#line hidden
, 982), false)
); );
WriteLiteral(" data-userid=\"");
#line 21 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(CurrentUser.UserId);
#line default
#line hidden
WriteLiteral("\"");
WriteLiteral(" data-uploadurl=\""); WriteLiteral(" data-uploadurl=\"");
#line 22 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 21 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(Url.Action(MVC.API.Device.AttachmentUpload(Model.Device.SerialNumber, null))); Write(Url.Action(MVC.API.Device.AttachmentUpload(Model.Device.SerialNumber, null)));
#line default #line default
@@ -106,8 +130,8 @@ WriteLiteral("\"");
WriteLiteral(" data-onlineuploadurl=\""); WriteLiteral(" data-onlineuploadurl=\"");
#line 22 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 21 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(Url.Action(MVC.API.Device.AttachmentOnlineUploadSession(Model.Device.SerialNumber))); Write(Url.Action(MVC.API.Device.AttachmentOnlineUploadSession(Model.Device.SerialNumber)));
#line default #line default
@@ -117,8 +141,8 @@ WriteLiteral("\"");
WriteLiteral(" data-qrcodeurl=\""); WriteLiteral(" data-qrcodeurl=\"");
#line 22 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 21 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(Url.Content("~/ClientSource/Scripts/Modules/qrcode.min.js")); Write(Url.Content("~/ClientSource/Scripts/Modules/qrcode.min.js"));
#line default #line default
@@ -130,7 +154,7 @@ WriteLiteral(">\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 23 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 22 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(Html.AntiForgeryToken()); Write(Html.AntiForgeryToken());
@@ -148,13 +172,13 @@ WriteLiteral(" class=\"attachmentOutput\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 28 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 27 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
#line default #line default
#line hidden #line hidden
#line 28 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 27 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
if (Model.Device.DeviceAttachments != null) if (Model.Device.DeviceAttachments != null)
{ {
foreach (var da in Model.Device.DeviceAttachments.OrderByDescending(a => a.Id)) foreach (var da in Model.Device.DeviceAttachments.OrderByDescending(a => a.Id))
@@ -163,23 +187,23 @@ WriteLiteral(">\r\n");
#line default #line default
#line hidden #line hidden
WriteLiteral(" <a"); WriteLiteral(" <a");
WriteAttribute("href", Tuple.Create(" href=\"", 1770), Tuple.Create("\"", 1830) WriteAttribute("href", Tuple.Create(" href=\"", 1912), Tuple.Create("\"", 1972)
#line 32 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 31 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
, Tuple.Create(Tuple.Create("", 1777), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Device.AttachmentDownload(da.Id)) , Tuple.Create(Tuple.Create("", 1919), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Device.AttachmentDownload(da.Id))
#line default #line default
#line hidden #line hidden
, 1777), false) , 1919), false)
); );
WriteLiteral(" data-attachmentid=\""); WriteLiteral(" data-attachmentid=\"");
#line 32 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 31 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(da.Id); Write(da.Id);
#line default #line default
@@ -189,54 +213,55 @@ WriteLiteral("\"");
WriteLiteral(" data-mimetype=\""); WriteLiteral(" data-mimetype=\"");
#line 32 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 31 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(da.MimeType); Write(da.MimeType);
#line default #line default
#line hidden #line hidden
WriteLiteral("\""); WriteLiteral("\"");
WriteLiteral(">\r\n <span"); WriteLiteral(">\r\n <span");
WriteLiteral(" class=\"icon\""); WriteLiteral(" class=\"icon\"");
WriteAttribute("title", Tuple.Create(" title=\"", 1940), Tuple.Create("\"", 1960) WriteAttribute("title", Tuple.Create(" title=\"", 2086), Tuple.Create("\"", 2106)
#line 33 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 32 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
, Tuple.Create(Tuple.Create("", 1948), Tuple.Create<System.Object, System.Int32>(da.Filename , Tuple.Create(Tuple.Create("", 2094), Tuple.Create<System.Object, System.Int32>(da.Filename
#line default #line default
#line hidden #line hidden
, 1948), false) , 2094), false)
); );
WriteLiteral(">\r\n <img"); WriteLiteral(">\r\n <img");
WriteLiteral(" alt=\"Attachment Thumbnail\""); WriteLiteral(" alt=\"Attachment Thumbnail\"");
WriteAttribute("src", Tuple.Create(" src=\"", 2031), Tuple.Create("\"", 2093) WriteAttribute("src", Tuple.Create(" src=\"", 2181), Tuple.Create("\"", 2243)
#line 34 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 33 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
, Tuple.Create(Tuple.Create("", 2037), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Device.AttachmentThumbnail(da.Id)) , Tuple.Create(Tuple.Create("", 2187), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Device.AttachmentThumbnail(da.Id))
#line default #line default
#line hidden #line hidden
, 2037), false) , 2187), false)
); );
WriteLiteral(" /></span>\r\n <span"); WriteLiteral(" />\r\n </span>\r\n " +
" <span");
WriteLiteral(" class=\"comments\""); WriteLiteral(" class=\"comments\"");
WriteAttribute("title", Tuple.Create(" title=\"", 2160), Tuple.Create("\"", 2197) WriteAttribute("title", Tuple.Create(" title=\"", 2352), Tuple.Create("\"", 2389)
#line 35 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 35 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
, Tuple.Create(Tuple.Create("", 2168), Tuple.Create<System.Object, System.Int32>(da.Comments ?? da.Filename , Tuple.Create(Tuple.Create("", 2360), Tuple.Create<System.Object, System.Int32>(da.Comments ?? da.Filename
#line default #line default
#line hidden #line hidden
, 2168), false) , 2360), false)
); );
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
@@ -249,40 +274,40 @@ WriteLiteral(">\r\n");
#line hidden #line hidden
#line 36 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 36 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
if (!string.IsNullOrEmpty(da.DocumentTemplateId)) if (!string.IsNullOrEmpty(da.DocumentTemplateId))
{ {
#line default #line default
#line hidden #line hidden
#line 37 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 37 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(da.DocumentTemplate.Description); Write(da.DocumentTemplate.Description);
#line default #line default
#line hidden #line hidden
#line 37 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 37 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
}
else
{
#line default
#line hidden
#line 39 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(da.Comments ?? da.Filename);
#line default
#line hidden
#line 39 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
} }
else
{
#line default #line default
#line hidden #line hidden
WriteLiteral("\r\n </span><span");
#line 39 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(da.Comments ?? da.Filename);
#line default
#line hidden
#line 39 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
}
#line default
#line hidden
WriteLiteral("\r\n </span><span");
WriteLiteral(" class=\"author\""); WriteLiteral(" class=\"author\"");
@@ -290,7 +315,7 @@ WriteLiteral(">");
#line 40 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 40 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(da.TechUser.ToString()); Write(da.TechUser.ToString());
#line default #line default
@@ -299,8 +324,8 @@ WriteLiteral("</span>");
#line 40 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 40 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
if (canRemoveAnyAttachments || (canRemoveOwnAttachments && da.TechUserId.Equals(CurrentUser.UserId, StringComparison.OrdinalIgnoreCase))) if (canRemoveAnyAttachments || (canRemoveOwnAttachments && da.TechUserId.Equals(CurrentUser.UserId, StringComparison.OrdinalIgnoreCase)))
{ {
#line default #line default
#line hidden #line hidden
@@ -312,7 +337,7 @@ WriteLiteral("></span>");
#line 41 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 41 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
} }
#line default #line default
#line hidden #line hidden
@@ -320,21 +345,21 @@ WriteLiteral("<span");
WriteLiteral(" class=\"timestamp\""); WriteLiteral(" class=\"timestamp\"");
WriteAttribute("title", Tuple.Create(" title=\"", 2888), Tuple.Create("\"", 2926) WriteAttribute("title", Tuple.Create(" title=\"", 3044), Tuple.Create("\"", 3082)
#line 41 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 41 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
, Tuple.Create(Tuple.Create("", 2896), Tuple.Create<System.Object, System.Int32>(da.Timestamp.ToFullDateTime() , Tuple.Create(Tuple.Create("", 3052), Tuple.Create<System.Object, System.Int32>(da.Timestamp.ToFullDateTime()
#line default #line default
#line hidden #line hidden
, 2896), false) , 3052), false)
); );
WriteLiteral(" data-livestamp=\""); WriteLiteral(" data-livestamp=\"");
#line 41 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 41 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(da.Timestamp.ToUnixEpoc()); Write(da.Timestamp.ToUnixEpoc());
#line default #line default
@@ -345,12 +370,12 @@ WriteLiteral(">");
#line 41 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 41 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(da.Timestamp.ToFullDateTime()); Write(da.Timestamp.ToFullDateTime());
#line default #line default
#line hidden #line hidden
WriteLiteral("</span>\r\n </a> \r\n"); WriteLiteral("</span>\r\n </a>\r\n");
#line 43 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 43 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
@@ -423,169 +448,51 @@ WriteLiteral(@">
modal: true modal: true
}); });
$(function () { $(function () {
var $Attachments = $('#Attachments'); const $Attachments = $('#Attachments');
var $attachmentOutput = $Attachments.find('.attachmentOutput'); const $attachmentOutput = $Attachments.find('.attachmentOutput');
var $attachmentDownloadHost; let $attachmentDownloadHost = null;
let $dialogRemoveAttachment = null;
var $dialogRemoveAttachment = null; function onAttachmentAdded(id, quick) {
var data = { id: id };
// Connect to Hub $.ajax({
var hub = $.connection.deviceUpdates; url: '");
// Map Functions
hub.client.addAttachment = onAddAttachment;
hub.client.removeAttachment = onRemoveAttachment;
$.connection.hub.qs = { DeviceSerialNumber: '");
#line 72 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 67 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(Model.Device.SerialNumber);
#line default
#line hidden
WriteLiteral("\' };\r\n $.connection.hub.error(onHubFailed);\r\n " +
" $.connection.hub.disconnected(onHubFailed);\r\n\r\n " +
" $.connection.hub.reconnecting(function () {\r\n " +
" $(\'#AttachmentsContainer\').find(\'span.action.enabled\').addClass(\'disa" +
"bled\');\r\n });\r\n $.connecti" +
"on.hub.reconnected(function () {\r\n $(\'#Attachment" +
"sContainer\').find(\'span.action.enabled\').removeClass(\'disabled\');\r\n " +
" });\r\n\r\n // Start Connection\r\n " +
" $.connection.hub.start(function () {\r\n " +
" $(\'#AttachmentsContainer\').find(\'span.action.enabled\').removeClass(\'dis" +
"abled\');\r\n }).fail(onHubFailed);\r\n\r\n " +
" function onHubFailed(error) {\r\n // Dis" +
"able UI\r\n $(\'#AttachmentsContainer\').find(\'span.a" +
"ction.enabled\').addClass(\'disabled\');\r\n\r\n // Show" +
" Dialog Message\r\n if ($(\'.disconnected-dialog\').l" +
"ength == 0) {\r\n $(\'<div>\')\r\n " +
" .addClass(\'dialog disconnected-dialog\')\r\n " +
" .html(\'<h3><span class=\"fa-stack fa-lg\"><i class=\"fa fa-" +
"wifi fa-stack-1x\"></i><i class=\"fa fa-ban fa-stack-2x error\"></i></span>Disconne" +
"cted from the Disco ICT Server</h3><div>This page is not receiving live updates." +
" Please ensure you are connected to the server, then refresh this page to enable" +
" features.</div>\')\r\n .dialog({\r\n " +
" resizable: false,\r\n " +
" title: \'Disconnected\',\r\n " +
" width: 400,\r\n modal: true,\r\n " +
" buttons: {\r\n " +
" \'Refresh Now\': function () {\r\n " +
" $(this).dialog(\'option\', \'buttons\', null);\r\n " +
" window.location.reload(true);\r\n " +
" },\r\n " +
" \'Close\': function () {\r\n " +
" $(this).dialog(\'destroy\');\r\n " +
" }\r\n }\r\n " +
" });\r\n }\r\n " +
"}\r\n\r\n function onAddAttachment(id, quick) {\r\n " +
" var data = { id: id };\r\n " +
"$.ajax({\r\n url: \'");
#line 118 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(Url.Action(MVC.API.Device.Attachment())); Write(Url.Action(MVC.API.Device.Attachment()));
#line default #line default
#line hidden #line hidden
WriteLiteral(@"', WriteLiteral("\',\r\n dataType: \'json\',\r\n " +
dataType: 'json', " data: data,\r\n success: function" +
data: data, " (d) {\r\n if (d.Result == \'OK\') {\r\n " +
success: function (d) { " var a = d.Attachment;\r\n\r\n " +
if (d.Result == 'OK') { " if ($Attachments.hasClass(\'canRemoveAnyAttachments\'))\r" +
var a = d.Attachment; "\n buildAttachment(a, true, quick)" +
"); ";\r\n else if ($Attachments.hasClass(\'c" +
"anRemoveOwnAttachments\'))\r\n build" +
"Attachment(a, (a.AuthorId === $Attachments.attr(\'data-userid\')), quick);\r\n " +
" else\r\n " +
" buildAttachment(a, false, quick);\r\n " +
" } else {\r\n alert(\'Unable to ad" +
"d attachment: \' + d.Result);\r\n }\r\n " +
" },\r\n error: func" +
"tion (jqXHR, textStatus, errorThrown) {\r\n " +
" alert(\'Unable to add attachment: \' + textStatus);\r\n " +
" }\r\n });\r\n }\r\n\r" +
"\n function buildAttachment(a, canRemove, quick) {\r\n " +
" var t = \'<a><span class=\"icon\"><img alt=\"Attachmen" +
"t Thumbnail\" /></span><span class=\"comments\"></span><span class=\"author\"></span>" +
"\';\r\n if (canRemove)\r\n " +
" t += \'<span class=\"remove fa fa-times-circle\"></span>\';\r\n " +
" t += \'<span class=\"timestamp\"></span></a>\';\r\n\r\n " +
" var e = $(t);\r\n\r\n e.attr(\'data-at" +
"tachmentid\', a.Id).attr(\'data-mimetype\', a.MimeType).attr(\'href\', \'");
#line 124 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 98 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
#line default
#line hidden
#line 124 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
if (canRemoveAnyAttachments)
{
#line default
#line hidden
WriteLiteral(" ");
WriteLiteral("buildAttachment(a, true, quick);");
WriteLiteral("\r\n");
#line 127 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
}
else if (canRemoveOwnAttachments)
{
#line default
#line hidden
WriteLiteral(" ");
WriteLiteral("buildAttachment(a, (a.AuthorId === \'");
#line 130 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(CurrentUser.UserId);
#line default
#line hidden
WriteLiteral("\'), quick);");
WriteLiteral("\r\n");
#line 131 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" ");
WriteLiteral("buildAttachment(a, false, quick);");
WriteLiteral("\r\n");
#line 135 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
}
#line default
#line hidden
WriteLiteral(@" } else {
alert('Unable to add attachment: ' + d.Result);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Unable to add attachment: ' + textStatus);
}
});
}
function buildAttachment(a, canRemove, quick) {
var t = '<a><span class=""icon""><img alt=""Attachment Thumbnail"" /></span><span class=""comments""></span><span class=""author""></span>';
if (canRemove)
t += '<span class=""remove fa fa-times-circle""></span>';
t += '<span class=""timestamp""></span></a>';
var e = $(t);
e.attr('data-attachmentid', a.Id).attr('data-mimetype', a.MimeType).attr('href', '");
#line 154 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(Url.Action(MVC.API.Device.AttachmentDownload())); Write(Url.Action(MVC.API.Device.AttachmentDownload()));
@@ -617,7 +524,7 @@ WriteLiteral(@"/' + a.Id);
img.attr('src', '"); img.attr('src', '");
#line 177 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 121 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(Url.Action(MVC.API.Device.AttachmentThumbnail())); Write(Url.Action(MVC.API.Device.AttachmentThumbnail()));
@@ -633,48 +540,50 @@ WriteLiteral("/\' + a.Id + \'?v=\' + retryCount);\r\n
" img.removeClass(\'loading\');\r\n });\r\n " + " img.removeClass(\'loading\');\r\n });\r\n " +
" window.setTimeout(setThumbnailUrl, 100);\r\n " + " window.setTimeout(setThumbnailUrl, 100);\r\n " +
" };\r\n buildThumbnail()" + " };\r\n buildThumbnail()" +
";\r\n }\r\n\r\n function onRemov" + ";\r\n }\r\n\r\n function onDownl" +
"eAttachment(id) {\r\n var a = $attachmentOutput.fin" + "oad() {\r\n var $this = $(this);\r\n " +
"d(\'a[data-attachmentid=\' + id + \']\');\r\n\r\n a.hide(" + " var url = $this.attr(\'href\');\r\n\r\n " +
"300).delay(300).queue(function () {\r\n var $th" + "if ($.connection && $.connection.hub && $.connection.hub.transport &&\r\n " +
"is = $(this);\r\n if ($this.attr(\'data-mimetype" + " $.connection.hub.transport.name == \'foreverFrame\') {\r" +
"\').toLowerCase().indexOf(\'image/\') == 0)\r\n " + "\n // SignalR active with foreverFrame transpo" +
" Shadowbox.removeCache(this);\r\n $this.find(\'" + "rt - use popup window\r\n window.open(url, \'_bl" +
".timestamp\').livestamp(\'destroy\');\r\n $this.re" + "ank\', \'height=150,width=250,location=no,menubar=no,resizable=no,scrollbars=no,st" +
"move();\r\n onUpdate();\r\n " + "atus=no,toolbar=no\');\r\n } else {\r\n " +
" });\r\n }\r\n\r\n func" + " // use iFrame\r\n if (!$at" +
"tion onDownload() {\r\n var $this = $(this);\r\n " + "tachmentDownloadHost) {\r\n $attachmentDown" +
" var url = $this.attr(\'href\');\r\n\r\n " + "loadHost = $(\'<iframe>\')\r\n .attr({ \'s" +
" if ($.connection && $.connection.hub && $.connection.hub.transport &" + "rc\': url, \'title\': \'Attachment Download Host\' })\r\n " +
"&\r\n $.connection.hub.transpor" + " .addClass(\'hidden\')\r\n ." +
"t.name == \'foreverFrame\') {\r\n // SignalR acti" + "appendTo(\'body\')\r\n .contents();\r\n " +
"ve with foreverFrame transport - use popup window\r\n " + " } else {\r\n " +
" window.open(url, \'_blank\', \'height=150,width=250,location=no,menubar=no,r" + " $attachmentDownloadHost[0].location.href = url;\r\n " +
"esizable=no,scrollbars=no,status=no,toolbar=no\');\r\n " + " }\r\n }\r\n\r\n r" +
" } else {\r\n // use iFrame\r\n " + "eturn false;\r\n }\r\n\r\n funct" +
" if (!$attachmentDownloadHost) {\r\n " + "ion onAttachmentRemoved(id) {\r\n var a = $attachme" +
" $attachmentDownloadHost = $(\'<iframe>\')\r\n " + "ntOutput.find(\'a[data-attachmentid=\' + id + \']\');\r\n\r\n " +
" .attr({ \'src\': url, \'title\': \'Attachment Download Host\' })\r\n " + " a.hide(300).delay(300).queue(function () {\r\n " +
" .addClass(\'hidden\')\r\n " + " var $this = $(this);\r\n if ($this.attr(\'d" +
" .appendTo(\'body\')\r\n " + "ata-mimetype\').toLowerCase().indexOf(\'image/\') == 0)\r\n " +
" .contents();\r\n } else {\r\n " + " Shadowbox.removeCache(this);\r\n " +
" $attachmentDownloadHost[0].location.href = url;\r\n " + "$this.find(\'.timestamp\').livestamp(\'destroy\');\r\n " +
" }\r\n }\r\n\r\n " + " $this.remove();\r\n onUpdate();\r\n " +
" return false;\r\n }\r\n\r\n " + " });\r\n }\r\n\r\n " +
" function onUpdate() {\r\n va" + " function onUpdate() {\r\n var attachmentCou" +
"r attachmentCount = $attachmentOutput.children(\'a\').length;\r\n " + "nt = $attachmentOutput.children(\'a\').length;\r\n va" +
" var tabHeading = \'Attachments [\' + attachmentCount + \']\';\r\n " + "r tabHeading = \'Attachments [\' + attachmentCount + \']\';\r\n " +
" $(\'#DeviceDetailTab-ResourcesLink\').text(tabHeading);\r\n " + " $(\'#DeviceDetailTab-ResourcesLink\').text(tabHeading);\r\n " +
" }\r\n\r\n"); " }\r\n\r\n document.DiscoFunctions.onAttachmen" +
"tAdded = onAttachmentAdded;\r\n document.DiscoFunctions" +
".onAttachmentRemoved = onAttachmentRemoved;\r\n\r\n");
#line 236 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 183 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
#line default #line default
#line hidden #line hidden
#line 236 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 183 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
if (canAddAttachments) if (canAddAttachments)
{ {
@@ -721,7 +630,7 @@ WriteLiteral("\r\n //#region Add Attachments\r\n
" //#endregion\r\n "); " //#endregion\r\n ");
#line 283 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 230 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
} }
@@ -730,7 +639,7 @@ WriteLiteral("\r\n //#region Add Attachments\r\n
WriteLiteral(" "); WriteLiteral(" ");
#line 284 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 231 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
if (canRemoveAnyAttachments || canRemoveOwnAttachments) if (canRemoveAnyAttachments || canRemoveOwnAttachments)
{ {
@@ -763,7 +672,7 @@ WriteLiteral(@"
url: '"); url: '");
#line 309 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 256 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(Url.Action(MVC.API.Device.AttachmentRemove())); Write(Url.Action(MVC.API.Device.AttachmentRemove()));
@@ -791,7 +700,7 @@ WriteLiteral("\',\r\n dataType: \'jso
"endregion\r\n "); "endregion\r\n ");
#line 336 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 283 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
} }
@@ -828,7 +737,7 @@ WriteLiteral("></i>&nbsp;Are you sure?\r\n </p>\r\n </div>\r\n <scr
"etailTab-ResourcesLink\">Attachments ["); "etailTab-ResourcesLink\">Attachments [");
#line 357 "..\..\Views\Device\DeviceParts\_Resources.cshtml" #line 304 "..\..\Views\Device\DeviceParts\_Resources.cshtml"
Write(Model.Device.DeviceAttachments == null ? 0 : Model.Device.DeviceAttachments.Count); Write(Model.Device.DeviceAttachments == null ? 0 : Model.Device.DeviceAttachments.Count);
+80 -3
View File
@@ -2,8 +2,15 @@
@using Disco.Services.Devices.DeviceFlags; @using Disco.Services.Devices.DeviceFlags;
@{ @{
ViewBag.Title = Html.ToBreadcrumb("Devices", MVC.Device.Index(), string.Format("Device: {0}", Model.Device.SerialNumber)); ViewBag.Title = Html.ToBreadcrumb("Devices", MVC.Device.Index(), string.Format("Device: {0}", Model.Device.SerialNumber));
var requiresLive = Authorization.HasAny(Claims.Device.ShowComments, Claims.Device.ShowAttachments);
if (requiresLive)
{
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
}
} }
<div id="Device_Show"> <div id="Device_Show" data-deviceserialnumber="@Model.Device.SerialNumber">
<div id="Device_Show_Status"> <div id="Device_Show_Status">
<i class="fa fa-square deviceStatus @(Model.Device.StatusCode())"></i>&nbsp;@Model.Device.Status() <i class="fa fa-square deviceStatus @(Model.Device.StatusCode())"></i>&nbsp;@Model.Device.Status()
<script type="text/javascript"> <script type="text/javascript">
@@ -93,9 +100,9 @@
</script> </script>
<div id="DeviceDetailTabs"> <div id="DeviceDetailTabs">
<ul id="DeviceDetailTabItems"></ul> <ul id="DeviceDetailTabItems"></ul>
@if (Authorization.Has(Claims.Device.ShowJobs)) @if (Authorization.HasAny(Claims.Device.ShowComments, Claims.Device.ShowJobs))
{ {
@Html.Partial(MVC.Device.Views.DeviceParts._Jobs, Model) @Html.Partial(MVC.Device.Views.DeviceParts._CommentsAndJobs, Model)
} }
@if (Authorization.Has(Claims.Device.ShowDetails)) @if (Authorization.Has(Claims.Device.ShowDetails))
{ {
@@ -118,4 +125,74 @@
@Html.Partial(MVC.Device.Views.DeviceParts._Certificates, Model) @Html.Partial(MVC.Device.Views.DeviceParts._Certificates, Model)
} }
</div> </div>
@if (requiresLive)
{
<script>
$(function () {
if (!document.DiscoFunctions)
return;
const deviceSerialNumber = $('#Device_Show').attr('data-deviceserialnumber');
// Connect to Hub
var hub = $.connection.deviceUpdates;
// Map Functions
if (document.DiscoFunctions.onCommentAdded)
hub.client.commentAdded = document.DiscoFunctions.onCommentAdded;
if (document.DiscoFunctions.onCommentRemoved)
hub.client.commentRemoved = document.DiscoFunctions.onCommentRemoved;
if (document.DiscoFunctions.onAttachmentAdded)
hub.client.attachmentAdded = document.DiscoFunctions.onAttachmentAdded;
if (document.DiscoFunctions.onAttachmentRemoved)
hub.client.attachmentRemoved = document.DiscoFunctions.onAttachmentRemoved;
$.connection.hub.qs = { DeviceSerialNumber: deviceSerialNumber };
$.connection.hub.error(onHubFailed);
$.connection.hub.disconnected(onHubFailed);
$.connection.hub.reconnecting(function () {
$('#AttachmentsContainer').find('span.action.enabled').addClass('disabled');
$('#Comments').find('button').prop('disabled', true);
});
$.connection.hub.reconnected(function () {
$('#AttachmentsContainer').find('span.action.enabled').removeClass('disabled');
$('#Comments').find('button').prop('disabled', false);
});
// Start Connection
$.connection.hub.start(function () {
$('#AttachmentsContainer').find('span.action.enabled').removeClass('disabled');
$('#Comments').find('button').prop('disabled', false);
}).fail(onHubFailed);
function onHubFailed(error) {
// Disable UI
$('#AttachmentsContainer').find('span.action.enabled').addClass('disabled');
$('#Comments').find('button').prop('disabled', true);
// Show Dialog Message
if ($('.disconnected-dialog').length == 0) {
$('<div>')
.addClass('dialog disconnected-dialog')
.html('<h3><span class="fa-stack fa-lg"><i class="fa fa-wifi fa-stack-1x"></i><i class="fa fa-ban fa-stack-2x error"></i></span>Disconnected from the Disco ICT Server</h3><div>This page is not receiving live updates. Please ensure you are connected to the server, then refresh this page to enable features.</div>')
.dialog({
resizable: false,
title: 'Disconnected',
width: 400,
modal: true,
buttons: {
'Refresh Now': function () {
$(this).dialog('option', 'buttons', null);
window.location.reload(true);
},
'Close': function () {
$(this).dialog('destroy');
}
}
});
}
}
});
</script>
}
</div> </div>
+143 -55
View File
@@ -54,6 +54,13 @@ namespace Disco.Web.Views.Device
ViewBag.Title = Html.ToBreadcrumb("Devices", MVC.Device.Index(), string.Format("Device: {0}", Model.Device.SerialNumber)); ViewBag.Title = Html.ToBreadcrumb("Devices", MVC.Device.Index(), string.Format("Device: {0}", Model.Device.SerialNumber));
var requiresLive = Authorization.HasAny(Claims.Device.ShowComments, Claims.Device.ShowAttachments);
if (requiresLive)
{
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
}
#line default #line default
#line hidden #line hidden
@@ -61,29 +68,40 @@ WriteLiteral("\r\n<div");
WriteLiteral(" id=\"Device_Show\""); WriteLiteral(" id=\"Device_Show\"");
WriteLiteral(" data-deviceserialnumber=\"");
#line 13 "..\..\Views\Device\Show.cshtml"
Write(Model.Device.SerialNumber);
#line default
#line hidden
WriteLiteral("\"");
WriteLiteral(">\r\n <div"); WriteLiteral(">\r\n <div");
WriteLiteral(" id=\"Device_Show_Status\""); WriteLiteral(" id=\"Device_Show_Status\"");
WriteLiteral(">\r\n <i"); WriteLiteral(">\r\n <i");
WriteAttribute("class", Tuple.Create(" class=\"", 290), Tuple.Create("\"", 352) WriteAttribute("class", Tuple.Create(" class=\"", 561), Tuple.Create("\"", 623)
, Tuple.Create(Tuple.Create("", 298), Tuple.Create("fa", 298), true) , Tuple.Create(Tuple.Create("", 569), Tuple.Create("fa", 569), true)
, Tuple.Create(Tuple.Create(" ", 300), Tuple.Create("fa-square", 301), true) , Tuple.Create(Tuple.Create(" ", 571), Tuple.Create("fa-square", 572), true)
, Tuple.Create(Tuple.Create(" ", 310), Tuple.Create("deviceStatus", 311), true) , Tuple.Create(Tuple.Create(" ", 581), Tuple.Create("deviceStatus", 582), true)
#line 8 "..\..\Views\Device\Show.cshtml" #line 15 "..\..\Views\Device\Show.cshtml"
, Tuple.Create(Tuple.Create(" ", 323), Tuple.Create<System.Object, System.Int32>(Model.Device.StatusCode() , Tuple.Create(Tuple.Create(" ", 594), Tuple.Create<System.Object, System.Int32>(Model.Device.StatusCode()
#line default #line default
#line hidden #line hidden
, 324), false) , 595), false)
); );
WriteLiteral("></i>&nbsp;"); WriteLiteral("></i>&nbsp;");
#line 8 "..\..\Views\Device\Show.cshtml" #line 15 "..\..\Views\Device\Show.cshtml"
Write(Model.Device.Status()); Write(Model.Device.Status());
@@ -97,13 +115,13 @@ WriteLiteral(">\r\n $(function () {\r\n $(\'#Device_Sh
"(\'#layout_PageHeading\')\r\n });\r\n </script>\r\n </div>\r\n"); "(\'#layout_PageHeading\')\r\n });\r\n </script>\r\n </div>\r\n");
#line 15 "..\..\Views\Device\Show.cshtml" #line 22 "..\..\Views\Device\Show.cshtml"
#line default #line default
#line hidden #line hidden
#line 15 "..\..\Views\Device\Show.cshtml" #line 22 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowFlagAssignments)) if (Authorization.Has(Claims.Device.ShowFlagAssignments))
{ {
@@ -117,13 +135,13 @@ WriteLiteral(" id=\"Device_Show_Flags\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 18 "..\..\Views\Device\Show.cshtml" #line 25 "..\..\Views\Device\Show.cshtml"
#line default #line default
#line hidden #line hidden
#line 18 "..\..\Views\Device\Show.cshtml" #line 25 "..\..\Views\Device\Show.cshtml"
foreach (var flag in Model.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId)))) foreach (var flag in Model.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId))))
{ {
@@ -132,27 +150,27 @@ WriteLiteral(">\r\n");
#line hidden #line hidden
WriteLiteral(" <i"); WriteLiteral(" <i");
WriteAttribute("class", Tuple.Create(" class=\"", 907), Tuple.Create("\"", 983) WriteAttribute("class", Tuple.Create(" class=\"", 1178), Tuple.Create("\"", 1254)
, Tuple.Create(Tuple.Create("", 915), Tuple.Create("flag", 915), true) , Tuple.Create(Tuple.Create("", 1186), Tuple.Create("flag", 1186), true)
, Tuple.Create(Tuple.Create(" ", 919), Tuple.Create("fa", 920), true) , Tuple.Create(Tuple.Create(" ", 1190), Tuple.Create("fa", 1191), true)
, Tuple.Create(Tuple.Create(" ", 922), Tuple.Create("fa-", 923), true) , Tuple.Create(Tuple.Create(" ", 1193), Tuple.Create("fa-", 1194), true)
#line 20 "..\..\Views\Device\Show.cshtml" #line 27 "..\..\Views\Device\Show.cshtml"
, Tuple.Create(Tuple.Create("", 926), Tuple.Create<System.Object, System.Int32>(flag.Item2.Icon , Tuple.Create(Tuple.Create("", 1197), Tuple.Create<System.Object, System.Int32>(flag.Item2.Icon
#line default #line default
#line hidden #line hidden
, 926), false) , 1197), false)
, Tuple.Create(Tuple.Create(" ", 944), Tuple.Create("fa-fw", 945), true) , Tuple.Create(Tuple.Create(" ", 1215), Tuple.Create("fa-fw", 1216), true)
, Tuple.Create(Tuple.Create(" ", 950), Tuple.Create("fa-lg", 951), true) , Tuple.Create(Tuple.Create(" ", 1221), Tuple.Create("fa-lg", 1222), true)
, Tuple.Create(Tuple.Create(" ", 956), Tuple.Create("d-", 957), true) , Tuple.Create(Tuple.Create(" ", 1227), Tuple.Create("d-", 1228), true)
#line 20 "..\..\Views\Device\Show.cshtml" #line 27 "..\..\Views\Device\Show.cshtml"
, Tuple.Create(Tuple.Create("", 959), Tuple.Create<System.Object, System.Int32>(flag.Item2.IconColour , Tuple.Create(Tuple.Create("", 1230), Tuple.Create<System.Object, System.Int32>(flag.Item2.IconColour
#line default #line default
#line hidden #line hidden
, 959), false) , 1230), false)
); );
WriteLiteral(">\r\n <span"); WriteLiteral(">\r\n <span");
@@ -166,7 +184,7 @@ WriteLiteral(" class=\"name\"");
WriteLiteral(">"); WriteLiteral(">");
#line 22 "..\..\Views\Device\Show.cshtml" #line 29 "..\..\Views\Device\Show.cshtml"
Write(flag.Item2.Name); Write(flag.Item2.Name);
@@ -175,7 +193,7 @@ WriteLiteral(">");
WriteLiteral("</span>"); WriteLiteral("</span>");
#line 22 "..\..\Views\Device\Show.cshtml" #line 29 "..\..\Views\Device\Show.cshtml"
if (flag.Item1.Comments != null) if (flag.Item1.Comments != null)
{ {
@@ -188,7 +206,7 @@ WriteLiteral(" class=\"comments\"");
WriteLiteral(">"); WriteLiteral(">");
#line 23 "..\..\Views\Device\Show.cshtml" #line 30 "..\..\Views\Device\Show.cshtml"
Write(flag.Item1.Comments.ToHtmlComment()); Write(flag.Item1.Comments.ToHtmlComment());
@@ -197,7 +215,7 @@ WriteLiteral(">");
WriteLiteral("</span>"); WriteLiteral("</span>");
#line 23 "..\..\Views\Device\Show.cshtml" #line 30 "..\..\Views\Device\Show.cshtml"
} }
#line default #line default
@@ -209,7 +227,7 @@ WriteLiteral(" class=\"added\"");
WriteLiteral(">"); WriteLiteral(">");
#line 23 "..\..\Views\Device\Show.cshtml" #line 30 "..\..\Views\Device\Show.cshtml"
Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser)); Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser));
@@ -218,7 +236,7 @@ WriteLiteral(">");
WriteLiteral("</span>\r\n </span>\r\n </i>\r\n"); WriteLiteral("</span>\r\n </span>\r\n </i>\r\n");
#line 26 "..\..\Views\Device\Show.cshtml" #line 33 "..\..\Views\Device\Show.cshtml"
} }
@@ -264,7 +282,7 @@ WriteLiteral(@">
"); ");
#line 59 "..\..\Views\Device\Show.cshtml" #line 66 "..\..\Views\Device\Show.cshtml"
} }
@@ -273,7 +291,7 @@ WriteLiteral(@">
WriteLiteral(" "); WriteLiteral(" ");
#line 60 "..\..\Views\Device\Show.cshtml" #line 67 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Subject, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._Subject, Model));
@@ -314,28 +332,28 @@ WriteLiteral(" id=\"DeviceDetailTabItems\"");
WriteLiteral("></ul>\r\n"); WriteLiteral("></ul>\r\n");
#line 96 "..\..\Views\Device\Show.cshtml" #line 103 "..\..\Views\Device\Show.cshtml"
#line default #line default
#line hidden #line hidden
#line 96 "..\..\Views\Device\Show.cshtml" #line 103 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowJobs)) if (Authorization.HasAny(Claims.Device.ShowComments, Claims.Device.ShowJobs))
{ {
#line default #line default
#line hidden #line hidden
#line 98 "..\..\Views\Device\Show.cshtml" #line 105 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Jobs, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._CommentsAndJobs, Model));
#line default #line default
#line hidden #line hidden
#line 98 "..\..\Views\Device\Show.cshtml" #line 105 "..\..\Views\Device\Show.cshtml"
} }
@@ -345,7 +363,7 @@ WriteLiteral("></ul>\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 100 "..\..\Views\Device\Show.cshtml" #line 107 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowDetails)) if (Authorization.Has(Claims.Device.ShowDetails))
{ {
@@ -353,14 +371,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 102 "..\..\Views\Device\Show.cshtml" #line 109 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Details, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._Details, Model));
#line default #line default
#line hidden #line hidden
#line 102 "..\..\Views\Device\Show.cshtml" #line 109 "..\..\Views\Device\Show.cshtml"
} }
@@ -370,7 +388,7 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 104 "..\..\Views\Device\Show.cshtml" #line 111 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowAssignmentHistory)) if (Authorization.Has(Claims.Device.ShowAssignmentHistory))
{ {
@@ -378,14 +396,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 106 "..\..\Views\Device\Show.cshtml" #line 113 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._AssignmentHistory, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._AssignmentHistory, Model));
#line default #line default
#line hidden #line hidden
#line 106 "..\..\Views\Device\Show.cshtml" #line 113 "..\..\Views\Device\Show.cshtml"
} }
@@ -395,7 +413,7 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 108 "..\..\Views\Device\Show.cshtml" #line 115 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowAttachments)) if (Authorization.Has(Claims.Device.ShowAttachments))
{ {
@@ -403,14 +421,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 110 "..\..\Views\Device\Show.cshtml" #line 117 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Resources, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._Resources, Model));
#line default #line default
#line hidden #line hidden
#line 110 "..\..\Views\Device\Show.cshtml" #line 117 "..\..\Views\Device\Show.cshtml"
} }
@@ -420,7 +438,7 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 112 "..\..\Views\Device\Show.cshtml" #line 119 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowFlagAssignments)) if (Authorization.Has(Claims.Device.ShowFlagAssignments))
{ {
@@ -428,14 +446,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 114 "..\..\Views\Device\Show.cshtml" #line 121 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Flags, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._Flags, Model));
#line default #line default
#line hidden #line hidden
#line 114 "..\..\Views\Device\Show.cshtml" #line 121 "..\..\Views\Device\Show.cshtml"
} }
@@ -445,7 +463,7 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 116 "..\..\Views\Device\Show.cshtml" #line 123 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowCertificates)) if (Authorization.Has(Claims.Device.ShowCertificates))
{ {
@@ -453,21 +471,91 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 118 "..\..\Views\Device\Show.cshtml" #line 125 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Certificates, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._Certificates, Model));
#line default #line default
#line hidden #line hidden
#line 118 "..\..\Views\Device\Show.cshtml" #line 125 "..\..\Views\Device\Show.cshtml"
} }
#line default #line default
#line hidden #line hidden
WriteLiteral(" </div>\r\n</div>\r\n"); WriteLiteral(" </div>\r\n");
#line 128 "..\..\Views\Device\Show.cshtml"
#line default
#line hidden
#line 128 "..\..\Views\Device\Show.cshtml"
if (requiresLive)
{
#line default
#line hidden
WriteLiteral(" <script>\r\n $(function () {\r\n if (!document.Disc" +
"oFunctions)\r\n return;\r\n\r\n const deviceSerialNu" +
"mber = $(\'#Device_Show\').attr(\'data-deviceserialnumber\');\r\n // Co" +
"nnect to Hub\r\n var hub = $.connection.deviceUpdates;\r\n\r\n " +
" // Map Functions\r\n if (document.DiscoFunctions.onCommentAd" +
"ded)\r\n hub.client.commentAdded = document.DiscoFunctions.onCo" +
"mmentAdded;\r\n if (document.DiscoFunctions.onCommentRemoved)\r\n " +
" hub.client.commentRemoved = document.DiscoFunctions.onCommentRem" +
"oved;\r\n if (document.DiscoFunctions.onAttachmentAdded)\r\n " +
" hub.client.attachmentAdded = document.DiscoFunctions.onAttachmentAdde" +
"d;\r\n if (document.DiscoFunctions.onAttachmentRemoved)\r\n " +
" hub.client.attachmentRemoved = document.DiscoFunctions.onAttachmentRem" +
"oved;\r\n\r\n $.connection.hub.qs = { DeviceSerialNumber: deviceSeria" +
"lNumber };\r\n $.connection.hub.error(onHubFailed);\r\n " +
" $.connection.hub.disconnected(onHubFailed);\r\n\r\n $.connection.hu" +
"b.reconnecting(function () {\r\n $(\'#AttachmentsContainer\').fin" +
"d(\'span.action.enabled\').addClass(\'disabled\');\r\n $(\'#Comments" +
"\').find(\'button\').prop(\'disabled\', true);\r\n });\r\n " +
"$.connection.hub.reconnected(function () {\r\n $(\'#AttachmentsC" +
"ontainer\').find(\'span.action.enabled\').removeClass(\'disabled\');\r\n " +
" $(\'#Comments\').find(\'button\').prop(\'disabled\', false);\r\n });" +
"\r\n\r\n // Start Connection\r\n $.connection.hub.start(" +
"function () {\r\n $(\'#AttachmentsContainer\').find(\'span.action." +
"enabled\').removeClass(\'disabled\');\r\n $(\'#Comments\').find(\'but" +
"ton\').prop(\'disabled\', false);\r\n }).fail(onHubFailed);\r\n\r\n " +
" function onHubFailed(error) {\r\n // Disable UI\r\n " +
" $(\'#AttachmentsContainer\').find(\'span.action.enabled\').addClass(\'" +
"disabled\');\r\n $(\'#Comments\').find(\'button\').prop(\'disabled\', " +
"true);\r\n\r\n // Show Dialog Message\r\n if ($(" +
"\'.disconnected-dialog\').length == 0) {\r\n $(\'<div>\')\r\n " +
" .addClass(\'dialog disconnected-dialog\')\r\n " +
" .html(\'<h3><span class=\"fa-stack fa-lg\"><i class=\"fa fa-wifi fa-sta" +
"ck-1x\"></i><i class=\"fa fa-ban fa-stack-2x error\"></i></span>Disconnected from t" +
"he Disco ICT Server</h3><div>This page is not receiving live updates. Please ens" +
"ure you are connected to the server, then refresh this page to enable features.<" +
"/div>\')\r\n .dialog({\r\n " +
"resizable: false,\r\n title: \'Disconnected\',\r\n " +
" width: 400,\r\n modal: t" +
"rue,\r\n buttons: {\r\n " +
" \'Refresh Now\': function () {\r\n $(th" +
"is).dialog(\'option\', \'buttons\', null);\r\n " +
"window.location.reload(true);\r\n },\r\n " +
" \'Close\': function () {\r\n " +
" $(this).dialog(\'destroy\');\r\n }\r\n " +
" }\r\n });\r\n " +
" }\r\n }\r\n });\r\n </script>\r\n");
#line 197 "..\..\Views\Device\Show.cshtml"
}
#line default
#line hidden
WriteLiteral("</div>\r\n");
} }
} }
+2 -2
View File
@@ -62,11 +62,11 @@
<ul id="jobDetailTabItems"> <ul id="jobDetailTabItems">
@if (Authorization.HasAll(Claims.Job.ShowLogs, Claims.Job.ShowAttachments)) @if (Authorization.HasAll(Claims.Job.ShowLogs, Claims.Job.ShowAttachments))
{ {
<li><a id="jobDetailTab-ResourcesLink" href="#jobDetailTab-Resources">Log and Attachments [@(Model.Job.JobAttachments.Count)]</a></li> <li><a id="jobDetailTab-ResourcesLink" href="#jobDetailTab-Resources">Comments and Attachments [@(Model.Job.JobAttachments.Count)]</a></li>
} }
else if (Authorization.Has(Claims.Job.ShowLogs)) else if (Authorization.Has(Claims.Job.ShowLogs))
{ {
<li><a id="jobDetailTab-ResourcesLink" href="#jobDetailTab-Resources">Log</a></li> <li><a id="jobDetailTab-ResourcesLink" href="#jobDetailTab-Resources">Comments</a></li>
} }
else if (Authorization.Has(Claims.Job.ShowAttachments)) else if (Authorization.Has(Claims.Job.ShowAttachments))
{ {
+3 -3
View File
@@ -265,11 +265,11 @@ WriteLiteral(" id=\"jobDetailTab-ResourcesLink\"");
WriteLiteral(" href=\"#jobDetailTab-Resources\""); WriteLiteral(" href=\"#jobDetailTab-Resources\"");
WriteLiteral(">Log and Attachments ["); WriteLiteral(">Comments and Attachments [");
#line 65 "..\..\Views\Job\Show.cshtml" #line 65 "..\..\Views\Job\Show.cshtml"
Write(Model.Job.JobAttachments.Count); Write(Model.Job.JobAttachments.Count);
#line default #line default
@@ -291,7 +291,7 @@ WriteLiteral(" id=\"jobDetailTab-ResourcesLink\"");
WriteLiteral(" href=\"#jobDetailTab-Resources\""); WriteLiteral(" href=\"#jobDetailTab-Resources\"");
WriteLiteral(">Log</a></li>\r\n"); WriteLiteral(">Comments</a></li>\r\n");
#line 70 "..\..\Views\Job\Show.cshtml" #line 70 "..\..\Views\Job\Show.cshtml"
@@ -35,16 +35,16 @@ namespace Disco.Web.Views.User.UserParts
using Disco.Web.Extensions; using Disco.Web.Extensions;
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")] [System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")]
[System.Web.WebPages.PageVirtualPathAttribute("~/Views/User/UserParts/Comments.cshtml")] [System.Web.WebPages.PageVirtualPathAttribute("~/Views/User/UserParts/_Comments.cshtml")]
public partial class Comments : Disco.Services.Web.WebViewPage<Disco.Web.Models.User.ShowModel> public partial class _Comments : Disco.Services.Web.WebViewPage<Disco.Web.Models.User.ShowModel>
{ {
public Comments() public _Comments()
{ {
} }
public override void Execute() public override void Execute()
{ {
#line 2 "..\..\Views\User\UserParts\Comments.cshtml" #line 2 "..\..\Views\User\UserParts\_Comments.cshtml"
Authorization.Require(Claims.User.ShowComments); Authorization.Require(Claims.User.ShowComments);
var canAddComments = Authorization.Has(Claims.User.Actions.AddComments); var canAddComments = Authorization.Has(Claims.User.Actions.AddComments);
@@ -60,21 +60,21 @@ WriteLiteral(" id=\"Comments\"");
WriteAttribute("class", Tuple.Create(" class=\"", 377), Tuple.Create("\"", 597) WriteAttribute("class", Tuple.Create(" class=\"", 377), Tuple.Create("\"", 597)
#line 8 "..\..\Views\User\UserParts\Comments.cshtml" #line 8 "..\..\Views\User\UserParts\_Comments.cshtml"
, Tuple.Create(Tuple.Create("", 385), Tuple.Create<System.Object, System.Int32>(canAddComments ? "canAddComments" : "cannotAddComments" , Tuple.Create(Tuple.Create("", 385), Tuple.Create<System.Object, System.Int32>(canAddComments ? "canAddComments" : "cannotAddComments"
#line default #line default
#line hidden #line hidden
, 385), false) , 385), false)
#line 8 "..\..\Views\User\UserParts\Comments.cshtml" #line 8 "..\..\Views\User\UserParts\_Comments.cshtml"
, Tuple.Create(Tuple.Create(" ", 443), Tuple.Create<System.Object, System.Int32>(canRemoveAnyComments ? "canRemoveAnyComments" : "cannotRemoveAnyComments" , Tuple.Create(Tuple.Create(" ", 443), Tuple.Create<System.Object, System.Int32>(canRemoveAnyComments ? "canRemoveAnyComments" : "cannotRemoveAnyComments"
#line default #line default
#line hidden #line hidden
, 444), false) , 444), false)
#line 8 "..\..\Views\User\UserParts\Comments.cshtml" #line 8 "..\..\Views\User\UserParts\_Comments.cshtml"
, Tuple.Create(Tuple.Create(" ", 520), Tuple.Create<System.Object, System.Int32>(canRemoveOwnComments ? "canRemoveOwnComments" : "cannotRemoveOwnComments" , Tuple.Create(Tuple.Create(" ", 520), Tuple.Create<System.Object, System.Int32>(canRemoveOwnComments ? "canRemoveOwnComments" : "cannotRemoveOwnComments"
#line default #line default
@@ -85,7 +85,7 @@ WriteAttribute("class", Tuple.Create(" class=\"", 377), Tuple.Create("\"", 597)
WriteLiteral(" data-id=\""); WriteLiteral(" data-id=\"");
#line 8 "..\..\Views\User\UserParts\Comments.cshtml" #line 8 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(Model.User.UserId); Write(Model.User.UserId);
@@ -96,7 +96,7 @@ WriteLiteral("\"");
WriteLiteral(" data-userid=\""); WriteLiteral(" data-userid=\"");
#line 8 "..\..\Views\User\UserParts\Comments.cshtml" #line 8 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(CurrentUser.UserId); Write(CurrentUser.UserId);
@@ -107,7 +107,7 @@ WriteLiteral("\"");
WriteLiteral(" data-addurl=\""); WriteLiteral(" data-addurl=\"");
#line 8 "..\..\Views\User\UserParts\Comments.cshtml" #line 8 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(Url.Action(MVC.API.User.CommentAdd(Model.User.UserId))); Write(Url.Action(MVC.API.User.CommentAdd(Model.User.UserId)));
@@ -118,7 +118,7 @@ WriteLiteral("\"");
WriteLiteral(" data-removeurl=\""); WriteLiteral(" data-removeurl=\"");
#line 8 "..\..\Views\User\UserParts\Comments.cshtml" #line 8 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(Url.Action(MVC.API.User.CommentRemove())); Write(Url.Action(MVC.API.User.CommentRemove()));
@@ -129,7 +129,7 @@ WriteLiteral("\"");
WriteLiteral(" data-geturl=\""); WriteLiteral(" data-geturl=\"");
#line 8 "..\..\Views\User\UserParts\Comments.cshtml" #line 8 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(Url.Action(MVC.API.User.Comment())); Write(Url.Action(MVC.API.User.Comment()));
@@ -142,7 +142,7 @@ WriteLiteral(">\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 9 "..\..\Views\User\UserParts\Comments.cshtml" #line 9 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(Html.AntiForgeryToken()); Write(Html.AntiForgeryToken());
@@ -151,13 +151,13 @@ Write(Html.AntiForgeryToken());
WriteLiteral("\r\n"); WriteLiteral("\r\n");
#line 10 "..\..\Views\User\UserParts\Comments.cshtml" #line 10 "..\..\Views\User\UserParts\_Comments.cshtml"
#line default #line default
#line hidden #line hidden
#line 10 "..\..\Views\User\UserParts\Comments.cshtml" #line 10 "..\..\Views\User\UserParts\_Comments.cshtml"
if (canAddComments) if (canAddComments)
{ {
@@ -189,7 +189,7 @@ WriteLiteral(" class=\"fa fa-comment\"");
WriteLiteral("></i></button>\r\n </div>\r\n"); WriteLiteral("></i></button>\r\n </div>\r\n");
#line 16 "..\..\Views\User\UserParts\Comments.cshtml" #line 16 "..\..\Views\User\UserParts\_Comments.cshtml"
} }
@@ -202,13 +202,13 @@ WriteLiteral(" class=\"commentOutput\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 18 "..\..\Views\User\UserParts\Comments.cshtml" #line 18 "..\..\Views\User\UserParts\_Comments.cshtml"
#line default #line default
#line hidden #line hidden
#line 18 "..\..\Views\User\UserParts\Comments.cshtml" #line 18 "..\..\Views\User\UserParts\_Comments.cshtml"
foreach (var c in Model.User.UserComments.OrderBy(m => m.Timestamp)) foreach (var c in Model.User.UserComments.OrderBy(m => m.Timestamp))
{ {
@@ -222,7 +222,7 @@ WriteLiteral(" class=\"comment\"");
WriteLiteral(" data-commentid=\""); WriteLiteral(" data-commentid=\"");
#line 20 "..\..\Views\User\UserParts\Comments.cshtml" #line 20 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(c.Id); Write(c.Id);
@@ -237,7 +237,7 @@ WriteLiteral(" class=\"author\"");
WriteLiteral(">"); WriteLiteral(">");
#line 21 "..\..\Views\User\UserParts\Comments.cshtml" #line 21 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(c.TechUser.ToStringFriendly()); Write(c.TechUser.ToStringFriendly());
@@ -246,7 +246,7 @@ WriteLiteral(">");
WriteLiteral("</span>"); WriteLiteral("</span>");
#line 21 "..\..\Views\User\UserParts\Comments.cshtml" #line 21 "..\..\Views\User\UserParts\_Comments.cshtml"
if (canRemoveAnyComments || (canRemoveOwnComments && c.TechUserId.Equals(CurrentUser.UserId, StringComparison.OrdinalIgnoreCase))) if (canRemoveAnyComments || (canRemoveOwnComments && c.TechUserId.Equals(CurrentUser.UserId, StringComparison.OrdinalIgnoreCase)))
{ {
@@ -259,7 +259,7 @@ WriteLiteral(" class=\"remove fa fa-times-circle\"");
WriteLiteral("></span>"); WriteLiteral("></span>");
#line 22 "..\..\Views\User\UserParts\Comments.cshtml" #line 22 "..\..\Views\User\UserParts\_Comments.cshtml"
} }
#line default #line default
@@ -271,7 +271,7 @@ WriteLiteral(" class=\"timestamp\"");
WriteLiteral(" data-livestamp=\""); WriteLiteral(" data-livestamp=\"");
#line 22 "..\..\Views\User\UserParts\Comments.cshtml" #line 22 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(c.Timestamp.ToUnixEpoc()); Write(c.Timestamp.ToUnixEpoc());
@@ -281,7 +281,7 @@ WriteLiteral("\"");
WriteAttribute("title", Tuple.Create(" title=\"", 1701), Tuple.Create("\"", 1738) WriteAttribute("title", Tuple.Create(" title=\"", 1701), Tuple.Create("\"", 1738)
#line 22 "..\..\Views\User\UserParts\Comments.cshtml" #line 22 "..\..\Views\User\UserParts\_Comments.cshtml"
, Tuple.Create(Tuple.Create("", 1709), Tuple.Create<System.Object, System.Int32>(c.Timestamp.ToFullDateTime() , Tuple.Create(Tuple.Create("", 1709), Tuple.Create<System.Object, System.Int32>(c.Timestamp.ToFullDateTime()
#line default #line default
@@ -292,7 +292,7 @@ WriteAttribute("title", Tuple.Create(" title=\"", 1701), Tuple.Create("\"", 1738
WriteLiteral(">"); WriteLiteral(">");
#line 22 "..\..\Views\User\UserParts\Comments.cshtml" #line 22 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(c.Timestamp.ToFullDateTime()); Write(c.Timestamp.ToFullDateTime());
@@ -305,7 +305,7 @@ WriteLiteral(" class=\"comment\"");
WriteLiteral(">"); WriteLiteral(">");
#line 23 "..\..\Views\User\UserParts\Comments.cshtml" #line 23 "..\..\Views\User\UserParts\_Comments.cshtml"
Write(c.Comments.ToHtmlComment()); Write(c.Comments.ToHtmlComment());
@@ -314,7 +314,7 @@ WriteLiteral(">");
WriteLiteral("</div>\r\n </div>\r\n"); WriteLiteral("</div>\r\n </div>\r\n");
#line 25 "..\..\Views\User\UserParts\Comments.cshtml" #line 25 "..\..\Views\User\UserParts\_Comments.cshtml"
} }
@@ -364,7 +364,7 @@ WriteLiteral(" </div>\r\n</div>\r\n<script>\r\n if (!document.DiscoFunctio
"tRemoved;\r\n });\r\n</script>\r\n"); "tRemoved;\r\n });\r\n</script>\r\n");
#line 107 "..\..\Views\User\UserParts\Comments.cshtml" #line 107 "..\..\Views\User\UserParts\_Comments.cshtml"
if (canAddComments) if (canAddComments)
{ {
@@ -396,14 +396,14 @@ WriteLiteral(" <script>\r\n $(function () {\r\n const $comm
"();\r\n }\r\n }\r\n });\r\n </script>\r\n"); "();\r\n }\r\n }\r\n });\r\n </script>\r\n");
#line 156 "..\..\Views\User\UserParts\Comments.cshtml" #line 156 "..\..\Views\User\UserParts\_Comments.cshtml"
} }
#line default #line default
#line hidden #line hidden
#line 157 "..\..\Views\User\UserParts\Comments.cshtml" #line 157 "..\..\Views\User\UserParts\_Comments.cshtml"
if (canRemoveAnyComments || canRemoveOwnComments) if (canRemoveAnyComments || canRemoveOwnComments)
{ {
@@ -440,9 +440,10 @@ WriteLiteral(" <script>\r\n $(function () {\r\n const $comm
"pt>\r\n"); "pt>\r\n");
#line 212 "..\..\Views\User\UserParts\Comments.cshtml" #line 212 "..\..\Views\User\UserParts\_Comments.cshtml"
} }
#line default #line default
#line hidden #line hidden
} }
@@ -26,7 +26,7 @@
@if (canShowComments) @if (canShowComments)
{ {
<div id="UserDetailTab-CommentsContainer"> <div id="UserDetailTab-CommentsContainer">
@Html.Partial(MVC.User.Views.UserParts.Comments, Model) @Html.Partial(MVC.User.Views.UserParts._Comments, Model)
</div> </div>
} }
@if (canShowJobs) @if (canShowJobs)
@@ -119,7 +119,7 @@ WriteLiteral(" ");
#line 29 "..\..\Views\User\UserParts\_CommentsAndJobs.cshtml" #line 29 "..\..\Views\User\UserParts\_CommentsAndJobs.cshtml"
Write(Html.Partial(MVC.User.Views.UserParts.Comments, Model)); Write(Html.Partial(MVC.User.Views.UserParts._Comments, Model));
#line default #line default
@@ -59,6 +59,7 @@
var $Attachments = $('#Attachments'); var $Attachments = $('#Attachments');
var $attachmentOutput = $Attachments.find('.attachmentOutput'); var $attachmentOutput = $Attachments.find('.attachmentOutput');
var $dialogRemoveAttachment = null; var $dialogRemoveAttachment = null;
let $attachmentDownloadHost = null;
function onAttachmentAdded(id, quick) { function onAttachmentAdded(id, quick) {
var data = { id: id }; var data = { id: id };
@@ -451,6 +451,7 @@ WriteLiteral(@">
var $Attachments = $('#Attachments'); var $Attachments = $('#Attachments');
var $attachmentOutput = $Attachments.find('.attachmentOutput'); var $attachmentOutput = $Attachments.find('.attachmentOutput');
var $dialogRemoveAttachment = null; var $dialogRemoveAttachment = null;
let $attachmentDownloadHost = null;
function onAttachmentAdded(id, quick) { function onAttachmentAdded(id, quick) {
var data = { id: id }; var data = { id: id };
@@ -458,7 +459,7 @@ WriteLiteral(@">
url: '"); url: '");
#line 66 "..\..\Views\User\UserParts\_Resources.cshtml" #line 67 "..\..\Views\User\UserParts\_Resources.cshtml"
Write(Url.Action(MVC.API.User.Attachment())); Write(Url.Action(MVC.API.User.Attachment()));
@@ -491,7 +492,7 @@ WriteLiteral("\',\r\n dataType: \'json\',\r\n
"chmentid\', a.Id).attr(\'data-mimetype\', a.MimeType).attr(\'href\', \'"); "chmentid\', a.Id).attr(\'data-mimetype\', a.MimeType).attr(\'href\', \'");
#line 96 "..\..\Views\User\UserParts\_Resources.cshtml" #line 97 "..\..\Views\User\UserParts\_Resources.cshtml"
Write(Url.Action(MVC.API.User.AttachmentDownload())); Write(Url.Action(MVC.API.User.AttachmentDownload()));
@@ -523,7 +524,7 @@ WriteLiteral(@"/' + a.Id);
img.attr('src', '"); img.attr('src', '");
#line 119 "..\..\Views\User\UserParts\_Resources.cshtml" #line 120 "..\..\Views\User\UserParts\_Resources.cshtml"
Write(Url.Action(MVC.API.User.AttachmentThumbnail())); Write(Url.Action(MVC.API.User.AttachmentThumbnail()));
@@ -576,13 +577,13 @@ WriteLiteral("/\' + a.Id + \'?v=\' + retryCount);\r\n
"DiscoFunctions.onAttachmentRemoved = onAttachmentRemoved;\r\n\r\n"); "DiscoFunctions.onAttachmentRemoved = onAttachmentRemoved;\r\n\r\n");
#line 181 "..\..\Views\User\UserParts\_Resources.cshtml" #line 182 "..\..\Views\User\UserParts\_Resources.cshtml"
#line default #line default
#line hidden #line hidden
#line 181 "..\..\Views\User\UserParts\_Resources.cshtml" #line 182 "..\..\Views\User\UserParts\_Resources.cshtml"
if (canAddAttachments) if (canAddAttachments)
{ {
@@ -629,7 +630,7 @@ WriteLiteral("\r\n //#region Add Attachments\r\n
" //#endregion\r\n "); " //#endregion\r\n ");
#line 228 "..\..\Views\User\UserParts\_Resources.cshtml" #line 229 "..\..\Views\User\UserParts\_Resources.cshtml"
} }
@@ -638,7 +639,7 @@ WriteLiteral("\r\n //#region Add Attachments\r\n
WriteLiteral(" "); WriteLiteral(" ");
#line 229 "..\..\Views\User\UserParts\_Resources.cshtml" #line 230 "..\..\Views\User\UserParts\_Resources.cshtml"
if (canRemoveAnyAttachments || canRemoveOwnAttachments) if (canRemoveAnyAttachments || canRemoveOwnAttachments)
{ {
@@ -672,7 +673,7 @@ WriteLiteral(@"
url: '"); url: '");
#line 255 "..\..\Views\User\UserParts\_Resources.cshtml" #line 256 "..\..\Views\User\UserParts\_Resources.cshtml"
Write(Url.Action(MVC.API.User.AttachmentRemove())); Write(Url.Action(MVC.API.User.AttachmentRemove()));
@@ -700,7 +701,7 @@ WriteLiteral("\',\r\n dataType: \'jso
"/#endregion\r\n "); "/#endregion\r\n ");
#line 283 "..\..\Views\User\UserParts\_Resources.cshtml" #line 284 "..\..\Views\User\UserParts\_Resources.cshtml"
} }
@@ -724,7 +725,7 @@ WriteLiteral(@"
$('#UserDetailTabItems').append('<li><a href=""#UserDetailTab-Resources"" id=""UserDetailTab-ResourcesLink"">Attachments ["); $('#UserDetailTabItems').append('<li><a href=""#UserDetailTab-Resources"" id=""UserDetailTab-ResourcesLink"">Attachments [");
#line 299 "..\..\Views\User\UserParts\_Resources.cshtml" #line 300 "..\..\Views\User\UserParts\_Resources.cshtml"
Write(Model.User.UserAttachments == null ? 0 : Model.User.UserAttachments.Count); Write(Model.User.UserAttachments == null ? 0 : Model.User.UserAttachments.Count);
@@ -733,7 +734,7 @@ WriteLiteral(@"
WriteLiteral("]</a></li>\');\r\n </script>\r\n</div>\r\n"); WriteLiteral("]</a></li>\');\r\n </script>\r\n</div>\r\n");
#line 302 "..\..\Views\User\UserParts\_Resources.cshtml" #line 303 "..\..\Views\User\UserParts\_Resources.cshtml"
if (canRemoveAnyAttachments || canRemoveOwnAttachments) if (canRemoveAnyAttachments || canRemoveOwnAttachments)
{ {
@@ -755,7 +756,7 @@ WriteLiteral(" class=\"fa fa-exclamation-triangle fa-lg\"");
WriteLiteral("></i>&nbsp;Are you sure?\r\n </p>\r\n </div>\r\n"); WriteLiteral("></i>&nbsp;Are you sure?\r\n </p>\r\n </div>\r\n");
#line 309 "..\..\Views\User\UserParts\_Resources.cshtml" #line 310 "..\..\Views\User\UserParts\_Resources.cshtml"
} }
#line default #line default