From 97ff42cab83087f78f4f76b803b3b536f53d1624 Mon Sep 17 00:00:00 2001 From: Johannes Lantz Date: Sat, 14 Mar 2026 17:13:11 +0100 Subject: [PATCH 1/8] Added pagination for history and comments --- .../uSupportTicketAuthorizedApiController.cs | 7 ++- ...ortTicketCommentAuthorizedApiController.cs | 21 ++++++--- .../Interfaces/IuSupportHistoryService.cs | 1 + .../Interfaces/IuSupportSettingsService.cs | 1 + .../IuSupportTicketCommentService.cs | 4 +- .../Services/uSupportTicketCommentService.cs | 44 ++++++++++++++++++- .../Services/uSupportTicketHistoryService.cs | 41 +++++++++++++++++ .../components/overlays/openTicket.html | 2 +- .../readonly/uSupport.readonly.controller.js | 2 - .../resources/uSupport.ticket.resources.js | 5 +++ .../uSupport.ticketComment.resources.js | 5 +++ .../tickets/uSupportCommentsComponent.html | 37 ++++++++++------ .../tickets/uSupportCommentsComponent.js | 18 ++++++-- 13 files changed, 157 insertions(+), 31 deletions(-) diff --git a/src/uSupport/Controllers/uSupportTicketAuthorizedApiController.cs b/src/uSupport/Controllers/uSupportTicketAuthorizedApiController.cs index c2820e3..2c53045 100644 --- a/src/uSupport/Controllers/uSupportTicketAuthorizedApiController.cs +++ b/src/uSupport/Controllers/uSupportTicketAuthorizedApiController.cs @@ -78,11 +78,10 @@ public uSupportPage GetPagedResolvedTickets(long page, string? s } [HttpGet] - public IEnumerable GetTicketHistory(Guid ticketId) - { - return _uSupportTicketHistoryService.GetByTicketId(ticketId); - } + public uSupportPage GetPagedHistoryByTicketId(Guid ticketId, long page) => _uSupportTicketHistoryService.GetPagedByTicketId(ticketId, page); + [HttpGet] + public IEnumerable GetTicketHistory(Guid ticketId) => _uSupportTicketHistoryService.GetByTicketId(ticketId); [HttpGet] public bool AnyResolvedTickets() => _uSupportTicketService.AnyResolvedTickets(); diff --git a/src/uSupport/Controllers/uSupportTicketCommentAuthorizedApiController.cs b/src/uSupport/Controllers/uSupportTicketCommentAuthorizedApiController.cs index 3685316..7b7d787 100644 --- a/src/uSupport/Controllers/uSupportTicketCommentAuthorizedApiController.cs +++ b/src/uSupport/Controllers/uSupportTicketCommentAuthorizedApiController.cs @@ -1,4 +1,5 @@ -using uSupport.Helpers; +using uSupport.Dtos; +using uSupport.Helpers; using uSupport.Dtos.Tables; using uSupport.Notifications; using Umbraco.Cms.Core.Events; @@ -43,7 +44,10 @@ public uSupportTicketCommentAuthorizedApiController( _uSupportTicketCommentService = uSupportTicketCommentService; } - [HttpGet] + [HttpGet] + public uSupportPage GetPagedCommentsForTicket(Guid ticketId, long page) => _uSupportTicketCommentService.GetPagedCommentsForTicket(ticketId, page); + + [HttpGet] public IEnumerable GetCommentsFromTicketId(Guid ticketId) => _uSupportTicketCommentService.GetCommentsFromTicketId(ticketId).ToList(); @@ -62,11 +66,18 @@ public ActionResult> Comment(uSupportTicketCo var updatedTicket =_uSupportTicketService.Update(ticket.ConvertDtoToSchema()); - string emailSetting = _uSupportSettingsService.GetTicketUpdateEmailSetting(); - if (!string.IsNullOrWhiteSpace(emailSetting)) + if (_uSupportSettingsService.GetSendEmailOnTicketCommentSetting()) { + string toAddress = _uSupportSettingsService.GetTicketUpdateEmailSetting(); + if (ticket.AuthorId != ticketComment.UserId) + { + var author = _userService.GetUserById(ticket.AuthorId); + if(author != null) + toAddress = author.Email; + } + _uSupportSettingsService.SendEmail( - emailSetting, + toAddress, _uSupportSettingsService.GetEmailSubjectUpdateTicket(), _uSupportSettingsService.GetEmailTemplateUpdateTicketPath(), ticket); diff --git a/src/uSupport/Services/Interfaces/IuSupportHistoryService.cs b/src/uSupport/Services/Interfaces/IuSupportHistoryService.cs index 66065e5..0c4d815 100644 --- a/src/uSupport/Services/Interfaces/IuSupportHistoryService.cs +++ b/src/uSupport/Services/Interfaces/IuSupportHistoryService.cs @@ -7,6 +7,7 @@ namespace uSupport.Services.Interfaces public interface IuSupportTicketHistoryService { IEnumerable GetByTicketId(Guid ticketId); + uSupportPage GetPagedByTicketId(Guid ticketId, long page); uSupportTicketHistory Get(Guid id); uSupportTicketHistory Create(uSupportTicketHistorySchema history); uSupportTicketHistory Update(uSupportTicketHistorySchema history); diff --git a/src/uSupport/Services/Interfaces/IuSupportSettingsService.cs b/src/uSupport/Services/Interfaces/IuSupportSettingsService.cs index e38fef8..0b0dd8b 100644 --- a/src/uSupport/Services/Interfaces/IuSupportSettingsService.cs +++ b/src/uSupport/Services/Interfaces/IuSupportSettingsService.cs @@ -7,6 +7,7 @@ public interface IuSupportSettingsService { void SendEmail(string toAddress, string subject, string templateViewPath, object model); bool GetSendEmailOnTicketCreatedSetting(); + bool GetSendEmailOnTicketCommentSetting(); string GetTicketUpdateEmailSetting(); string GetEmailSubjectNewTicket(uSupportTicket? ticket = null); string GetEmailSubjectUpdateTicket(uSupportTicket? ticket = null); diff --git a/src/uSupport/Services/Interfaces/IuSupportTicketCommentService.cs b/src/uSupport/Services/Interfaces/IuSupportTicketCommentService.cs index 2161f71..c31774b 100644 --- a/src/uSupport/Services/Interfaces/IuSupportTicketCommentService.cs +++ b/src/uSupport/Services/Interfaces/IuSupportTicketCommentService.cs @@ -1,4 +1,5 @@ -using uSupport.Dtos.Tables; +using uSupport.Dtos; +using uSupport.Dtos.Tables; using uSupport.Migrations.Schemas; namespace uSupport.Services.Interfaces @@ -6,6 +7,7 @@ namespace uSupport.Services.Interfaces public interface IuSupportTicketCommentService { IEnumerable GetCommentsFromTicketId(Guid ticketId); + uSupportPage GetPagedCommentsForTicket(Guid ticketId, long page); IEnumerable GetAll(); uSupportTicketComment Get(Guid id); uSupportTicketComment Create(uSupportTicketCommentSchema comment); diff --git a/src/uSupport/Services/uSupportTicketCommentService.cs b/src/uSupport/Services/uSupportTicketCommentService.cs index 984c380..2046991 100644 --- a/src/uSupport/Services/uSupportTicketCommentService.cs +++ b/src/uSupport/Services/uSupportTicketCommentService.cs @@ -1,13 +1,14 @@ using NPoco; -using uSupport.Helpers; +using uSupport.Dtos; using uSupport.Dtos.Tables; using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Services; using uSupport.Migrations.Schemas; using uSupport.Services.Interfaces; -using Umbraco.Cms.Infrastructure.Scoping; using Umbraco.Cms.Core.Models.Membership; +using Umbraco.Cms.Infrastructure.Scoping; using Umbraco.Cms.Core.Models.ContentEditing; +using static uSupport.Helpers.uSupportPageHelper; using static uSupport.Constants.uSupportConstants; namespace uSupport.Services @@ -77,6 +78,45 @@ public IEnumerable GetCommentsFromTicketId(Guid ticketId) } } + public uSupportPage GetPagedCommentsForTicket(Guid ticketId, long page) + { + var context = GetScope(); + try + { + var sql = new Sql() + .Select("*") + .From(TicketCommentTableAlias) + .Where($"{TicketCommentTableAlias}.TicketId = UPPER('{ticketId}')") + .OrderBy($"{TicketCommentTableAlias}.Date DESC"); + + var sqlCount = new Sql() + .Select($"COUNT({TicketCommentTableAlias}.Id)") + .From(TicketCommentTableAlias) + .Where($"{TicketCommentTableAlias}.TicketId = UPPER('{ticketId}')"); + + var commentCount = context.Scope.Database.Fetch(sqlCount).FirstOrDefault(); + var comments = context.Scope.Database.SkipTake((page - 1) * PageSize, PageSize, sql); + + List commentDtos = new List(); + + foreach (var comment in comments.ToList()) + { + var user = _userService.GetUserById(comment.UserId); + + comment.User = _umbracoMapper.Map(user); + + commentDtos.Add(comment); + } + + return MapPageToUSupportPage(commentDtos, commentCount, page, PageSize); + } + finally + { + if (context.Created) + context.Scope.Dispose(); + } + } + public void DeleteByTicketId(Guid ticketId) { var context = GetScope(); diff --git a/src/uSupport/Services/uSupportTicketHistoryService.cs b/src/uSupport/Services/uSupportTicketHistoryService.cs index 4c697f4..d28fb70 100644 --- a/src/uSupport/Services/uSupportTicketHistoryService.cs +++ b/src/uSupport/Services/uSupportTicketHistoryService.cs @@ -8,7 +8,9 @@ using uSupport.Services.Interfaces; using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Infrastructure.Scoping; +using Org.BouncyCastle.Utilities.Collections; using Umbraco.Cms.Core.Models.ContentEditing; +using static uSupport.Helpers.uSupportPageHelper; using static uSupport.Constants.uSupportConstants; namespace uSupport.Services @@ -59,6 +61,45 @@ public IEnumerable GetByTicketId(Guid ticketId) } } + + public uSupportPage GetPagedByTicketId(Guid ticketId, long page) + { + var context = GetScope(); + try + { + var sql = new Sql() + .Select("*") + .From(TicketHistoryTableAlias) + .Where($"{TicketHistoryTableAlias}.TicketId = UPPER('{ticketId}')") + .OrderBy($"{TicketHistoryTableAlias}.Date DESC"); + + var sqlCount = new Sql() + .Select($"COUNT({TicketHistoryTableAlias}.Id)") + .From(TicketHistoryTableAlias) + .Where($"{TicketHistoryTableAlias}.TicketId = UPPER('{ticketId}')"); + + var historyCount = context.Scope.Database.Fetch(sqlCount).FirstOrDefault(); + var history = context.Scope.Database.SkipTake((page - 1) * PageSize, PageSize, sql); + + foreach (var item in history) + { + var user = _userService.GetUserById(item.UserId); + if (user != null) + item.User = _umbracoMapper.Map(user); + + if (!string.IsNullOrWhiteSpace(item.ChangesJson)) + item.Changes = JsonSerializer.Deserialize>(item.ChangesJson); + } + + return MapPageToUSupportPage(history, historyCount, page, PageSize); + } + finally + { + if (context.Created) + context.Scope.Dispose(); + } + } + public void DeleteByTicketId(Guid ticketId) { var context = GetScope(); diff --git a/src/uSupport/wwwroot/components/overlays/openTicket.html b/src/uSupport/wwwroot/components/overlays/openTicket.html index 54ee792..b72cdb7 100644 --- a/src/uSupport/wwwroot/components/overlays/openTicket.html +++ b/src/uSupport/wwwroot/components/overlays/openTicket.html @@ -86,5 +86,5 @@ - + \ No newline at end of file diff --git a/src/uSupport/wwwroot/components/propertyEditors/readonly/uSupport.readonly.controller.js b/src/uSupport/wwwroot/components/propertyEditors/readonly/uSupport.readonly.controller.js index 7105b0c..414531d 100644 --- a/src/uSupport/wwwroot/components/propertyEditors/readonly/uSupport.readonly.controller.js +++ b/src/uSupport/wwwroot/components/propertyEditors/readonly/uSupport.readonly.controller.js @@ -7,8 +7,6 @@ } }); - console.log($scope.model) - $scope.openEditor = function (node) { if ($scope.model.admin) { var overlay = { diff --git a/src/uSupport/wwwroot/components/resources/uSupport.ticket.resources.js b/src/uSupport/wwwroot/components/resources/uSupport.ticket.resources.js index e9a3cf2..6244131 100644 --- a/src/uSupport/wwwroot/components/resources/uSupport.ticket.resources.js +++ b/src/uSupport/wwwroot/components/resources/uSupport.ticket.resources.js @@ -36,6 +36,11 @@ $http.get(uSupportConfig.baseApiUrl + "uSupportTicketAuthorizedApi/GetTicket?ticketId=" + ticketId) ); }, + getPagedHistoryByTicketId: function (ticketId, page) { + return umbRequestHelper.resourcePromise( + $http.get(uSupportConfig.baseApiUrl + "uSupportTicketAuthorizedApi/GetPagedHistoryByTicketId?ticketId=" + ticketId + "&page=" + page) + ); + }, getPagedActiveTickets: function (page, searchTerm, sort) { var url = uSupportConfig.baseApiUrl + "uSupportTicketAuthorizedApi/GetPagedActiveTickets?page=" + page + "&sortColumnName=" + sort.column + "&sortReverse=" + sort.reverse; diff --git a/src/uSupport/wwwroot/components/resources/uSupport.ticketComment.resources.js b/src/uSupport/wwwroot/components/resources/uSupport.ticketComment.resources.js index 57281a4..8527197 100644 --- a/src/uSupport/wwwroot/components/resources/uSupport.ticketComment.resources.js +++ b/src/uSupport/wwwroot/components/resources/uSupport.ticketComment.resources.js @@ -16,6 +16,11 @@ $http.get(uSupportConfig.baseApiUrl + "uSupportTicketCommentAuthorizedApi/GetCommentsFromTicketId?ticketId=" + id) ); }, + getPagedCommentsForTicket: function (ticketId, page) { + return umbRequestHelper.resourcePromise( + $http.get(uSupportConfig.baseApiUrl + "uSupportTicketCommentAuthorizedApi/GetPagedCommentsForTicket?ticketId=" + ticketId + "&page=" + page) + ); + }, }; }); })(); \ No newline at end of file diff --git a/src/uSupport/wwwroot/components/tickets/uSupportCommentsComponent.html b/src/uSupport/wwwroot/components/tickets/uSupportCommentsComponent.html index 6c7d3be..c03b2b3 100644 --- a/src/uSupport/wwwroot/components/tickets/uSupportCommentsComponent.html +++ b/src/uSupport/wwwroot/components/tickets/uSupportCommentsComponent.html @@ -13,7 +13,7 @@
{{comment.User.name}}
-
{{comment.Date | date:'yyyy-MM-dd'}}
+
{{comment.Date | date:'yyyy-MM-dd HH:mm'}}
@@ -23,16 +23,27 @@
-
- -
+ + -
- - -
+
+
+ +
+ +
+ + +
+
\ No newline at end of file diff --git a/src/uSupport/wwwroot/components/tickets/uSupportCommentsComponent.js b/src/uSupport/wwwroot/components/tickets/uSupportCommentsComponent.js index f324d0d..d75c6e1 100644 --- a/src/uSupport/wwwroot/components/tickets/uSupportCommentsComponent.js +++ b/src/uSupport/wwwroot/components/tickets/uSupportCommentsComponent.js @@ -2,13 +2,25 @@ templateUrl: "/App_Plugins/uSupport/components/tickets/uSupportcommentsComponent.html", controllerAs: "vm", bindings: { - comments: "=", ticketId: "=", userId: "=", adminView: "=" }, controller: function (uSupportTicketCommentResources, notificationsService) { var vm = this; + vm.comments = [] + + vm.$onInit = function () { + (vm.loadComments = function (pageNumber) { + uSupportTicketCommentResources.getPagedCommentsForTicket(vm.ticketId, pageNumber).then(function (comments) { + vm.comments = comments.Items; + vm.pagination = { + pageNumber: pageNumber, + totalPages: comments.TotalPages + }; + }); + })(1); + } vm.addComment = function () { vm.commentbuttonState = "busy"; @@ -16,10 +28,10 @@ TicketId: vm.ticketId, UserId: vm.userId, Comment: vm.comment - }).then(function (comments) { - vm.comments = comments; + }).then(function () { vm.commentbuttonState = "success"; vm.comment = ""; + vm.$onInit(); }, function (err) { if (err.data && (err.data.message || err.data.Detail)) { notificationsService.error("uSupport", err.data.message ?? err.data.Detail); From 436e622636f8ab47b2f2d7f6916748ade34802de Mon Sep 17 00:00:00 2001 From: Johannes Lantz Date: Sat, 14 Mar 2026 19:49:02 +0100 Subject: [PATCH 2/8] Improved ticket history and fixed default send email --- .../Composers/uSupportNotificationComposer.cs | 8 ++- ...ortTicketCommentAuthorizedApiController.cs | 4 +- .../Dtos/Settings/uSupportSettingsTicket.cs | 7 +- src/uSupport/Helpers/uSupportPageHelper.cs | 9 +-- .../TicketHistoryNotificationHandler.cs | 58 ++++++++++++++-- .../Tickets/EmailSendingNotification.cs | 20 ++++++ .../Services/uSupportSettingsService.cs | 64 +++++++++++++----- .../Services/uSupportTicketService.cs | 3 +- .../uSupport/Emails}/NewTicketEmail.cshtml | 6 +- .../uSupport/Emails}/UpdateTicketEmail.cshtml | 66 ++++++++++--------- src/uSupport/uSupport.csproj | 7 +- .../settings/settings.overview.controller.js | 6 +- .../apps/history/history.controller.js | 20 +++++- .../tickets/apps/history/history.html | 20 ++++-- .../tickets/apps/ticket/ticket.html | 2 +- .../tickets/tickets.edit.controller.js | 4 +- 16 files changed, 215 insertions(+), 89 deletions(-) create mode 100644 src/uSupport/Notifications/Tickets/EmailSendingNotification.cs rename src/uSupport/{wwwroot/templates => Views/Partials/uSupport/Emails}/NewTicketEmail.cshtml (96%) rename src/uSupport/{wwwroot/templates => Views/Partials/uSupport/Emails}/UpdateTicketEmail.cshtml (70%) diff --git a/src/uSupport/Composers/uSupportNotificationComposer.cs b/src/uSupport/Composers/uSupportNotificationComposer.cs index a4c0655..bab1e2e 100644 --- a/src/uSupport/Composers/uSupportNotificationComposer.cs +++ b/src/uSupport/Composers/uSupportNotificationComposer.cs @@ -1,7 +1,8 @@ using uSupport.Notifications; using Umbraco.Cms.Core.Composing; -using Umbraco.Cms.Core.DependencyInjection; +using uSupport.Notifications.Tickets; using uSupport.Notifications.Handlers; +using Umbraco.Cms.Core.DependencyInjection; namespace uSupport.Composers { @@ -9,7 +10,10 @@ public class uSupportNotificationComposer : IComposer { public void Compose(IUmbracoBuilder builder) { - builder.AddNotificationHandler(); + builder.AddNotificationHandler() + .AddNotificationHandler() + .AddNotificationHandler() + .AddNotificationHandler(); } } } \ No newline at end of file diff --git a/src/uSupport/Controllers/uSupportTicketCommentAuthorizedApiController.cs b/src/uSupport/Controllers/uSupportTicketCommentAuthorizedApiController.cs index 7b7d787..6bd451a 100644 --- a/src/uSupport/Controllers/uSupportTicketCommentAuthorizedApiController.cs +++ b/src/uSupport/Controllers/uSupportTicketCommentAuthorizedApiController.cs @@ -78,9 +78,9 @@ public ActionResult> Comment(uSupportTicketCo _uSupportSettingsService.SendEmail( toAddress, - _uSupportSettingsService.GetEmailSubjectUpdateTicket(), + _uSupportSettingsService.GetEmailSubjectUpdateTicket(updatedTicket), _uSupportSettingsService.GetEmailTemplateUpdateTicketPath(), - ticket); + updatedTicket); } _eventAggregator.Publish(new AddTicketCommentNotification(updatedTicket, comment)); diff --git a/src/uSupport/Dtos/Settings/uSupportSettingsTicket.cs b/src/uSupport/Dtos/Settings/uSupportSettingsTicket.cs index cf2850b..c30d8ea 100644 --- a/src/uSupport/Dtos/Settings/uSupportSettingsTicket.cs +++ b/src/uSupport/Dtos/Settings/uSupportSettingsTicket.cs @@ -6,10 +6,11 @@ public class uSupportSettingsTicket { public const string Tickets = uSupportConstants.SectionAlias + ":Settings:Tickets"; public bool SendEmailOnTicketCreated { get; set; } = true; + public bool SendEmailOnTicketComment { get; set; } = true; public string TicketUpdateEmail { get; set; } = "None"; public string EmailSubjectNewTicket { get; set; } = "A new ticket '{ExternalTicketId}' has been created"; public string EmailSubjectUpdateTicket { get; set; } = "Ticket '{ExternalTicketId}' has been updated"; - public string EmailTemplateNewTicketPath { get; set; } = "/App_Plugins/uSupport/templates/NewTicketEmail.cshtml"; - public string EmailTemplateUpdateTicketPath { get; set; } = "/App_Plugins/uSupport/templates/UpdateTicketEmail.cshtml"; + public string EmailTemplateNewTicketPath { get; set; } = "/Views/Partials/uSupport/Emails/NewTicketEmail.cshtml"; + public string EmailTemplateUpdateTicketPath { get; set; } = "/Views/Partials/uSupport/Emails/UpdateTicketEmail.cshtml"; } -} \ No newline at end of file +} diff --git a/src/uSupport/Helpers/uSupportPageHelper.cs b/src/uSupport/Helpers/uSupportPageHelper.cs index 667d143..4155963 100644 --- a/src/uSupport/Helpers/uSupportPageHelper.cs +++ b/src/uSupport/Helpers/uSupportPageHelper.cs @@ -1,15 +1,12 @@ -using System; -using uSupport.Dtos; -using uSupport.Dtos.Tables; -using System.Collections.Generic; +using uSupport.Dtos; namespace uSupport.Helpers { public static class uSupportPageHelper { - public static uSupportPage MapPageToUSupportPage(List items, long totalItems, long currentPage, long itemsPerPage) + public static uSupportPage MapPageToUSupportPage(List items, long totalItems, long currentPage, long itemsPerPage) { - uSupportPage page = new uSupportPage() + uSupportPage page = new uSupportPage() { TotalItems = totalItems, ItemsPerPage = itemsPerPage, diff --git a/src/uSupport/Notifications/Handlers/TicketHistoryNotificationHandler.cs b/src/uSupport/Notifications/Handlers/TicketHistoryNotificationHandler.cs index 2abe770..b6785a9 100644 --- a/src/uSupport/Notifications/Handlers/TicketHistoryNotificationHandler.cs +++ b/src/uSupport/Notifications/Handlers/TicketHistoryNotificationHandler.cs @@ -3,10 +3,14 @@ using Umbraco.Cms.Core.Events; using uSupport.Migrations.Schemas; using uSupport.Services.Interfaces; +using uSupport.Notifications.Tickets; namespace uSupport.Notifications.Handlers { - public class TicketHistoryNotificationHandler : INotificationHandler + public class TicketHistoryNotificationHandler : INotificationHandler, + INotificationHandler, + INotificationHandler, + INotificationHandler { private readonly IuSupportTicketHistoryService _uSupportTicketHistoryService; public TicketHistoryNotificationHandler(IuSupportTicketHistoryService uSupportTicketHistoryService) @@ -20,14 +24,9 @@ public void Handle(TicketHistoryNotification notification) { TicketId = notification.NewTicket.Id, UserId = notification.UserId, - ActionType = notification.OldTicket == null ? "Created" : "Updated", + ActionType = "Updated", }; - if (notification.OldTicket == null) - { - _uSupportTicketHistoryService.Create(history); - return; - } var changes = new List(); @@ -71,5 +70,50 @@ public void Handle(TicketHistoryNotification notification) _uSupportTicketHistoryService.Create(history); } + + public void Handle(CreateTicketNotification notification) + { + _uSupportTicketHistoryService.Create(new uSupportTicketHistorySchema() + { + TicketId = notification.Ticket.Id, + UserId = notification.Ticket.AuthorId, + ActionType = "Created", + }); + } + + public void Handle(EmailSendingNotification notification) + { + _uSupportTicketHistoryService.Create(new uSupportTicketHistorySchema() + { + TicketId = notification.TicketId, + UserId = 0, + ActionType = "SentEmail", + ChangesJson = JsonSerializer.Serialize(new List() + { + new uSupportChange() + { + Field = "Email", + New = notification.ToAddress + } + }) + }); + } + + public void Handle(AddTicketCommentNotification notification) + { + _uSupportTicketHistoryService.Create(new uSupportTicketHistorySchema() + { + TicketId = notification.Ticket.Id, + UserId = notification.Comment.UserId, + ActionType = "Comment", + ChangesJson = JsonSerializer.Serialize(new List() + { + new uSupportChange() + { + Field = "Comment" + } + }) + }); + } } } diff --git a/src/uSupport/Notifications/Tickets/EmailSendingNotification.cs b/src/uSupport/Notifications/Tickets/EmailSendingNotification.cs new file mode 100644 index 0000000..1733aa2 --- /dev/null +++ b/src/uSupport/Notifications/Tickets/EmailSendingNotification.cs @@ -0,0 +1,20 @@ +using Umbraco.Cms.Core.Notifications; + +namespace uSupport.Notifications.Tickets +{ + public class EmailSendingNotification : INotification + { + public Guid TicketId { get; } + public string ToAddress { get; } + public string Subject { get; } + public string TemplatePath { get; } + + public EmailSendingNotification(Guid ticketId, string toAddress, string subject, string templatePath) + { + TicketId = ticketId; + ToAddress = toAddress; + Subject = subject; + TemplatePath = templatePath; + } + } +} \ No newline at end of file diff --git a/src/uSupport/Services/uSupportSettingsService.cs b/src/uSupport/Services/uSupportSettingsService.cs index b6c5b92..93ce518 100644 --- a/src/uSupport/Services/uSupportSettingsService.cs +++ b/src/uSupport/Services/uSupportSettingsService.cs @@ -2,14 +2,17 @@ using uSupport.Dtos.Tables; using Umbraco.Cms.Core.Mail; using uSupport.Dtos.Settings; +using Umbraco.Cms.Core.Events; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using uSupport.Services.Interfaces; +using Microsoft.AspNetCore.Hosting; using Umbraco.Cms.Core.Models.Email; using Microsoft.AspNetCore.Mvc.Razor; +using uSupport.Notifications.Tickets; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.AspNetCore.Mvc.Abstractions; @@ -21,35 +24,50 @@ namespace uSupport.Services { public class uSupportSettingsService : IuSupportSettingsService { + private const string LegacyNewTicketTemplatePath = "/App_Plugins/uSupport/templates/NewTicketEmail.cshtml"; + private const string LegacyUpdateTicketTemplatePath = "/App_Plugins/uSupport/templates/UpdateTicketEmail.cshtml"; + private const string DefaultNewTicketTemplatePath = "/Views/uSupport/Emails/NewTicketEmail.cshtml"; + private const string DefaultUpdateTicketTemplatePath = "/Views/uSupport/Emails/UpdateTicketEmail.cshtml"; + private readonly uSupportSettingsTicket _defaultSettings; + private readonly ILogger _logger; private readonly IEmailSender _emailSender; + private readonly IEventAggregator _eventAggregator; private readonly IRazorViewEngine _razorViewEngine; + private readonly ITempDataProvider _tempDataProvider; + private readonly IWebHostEnvironment _webHostEnvironment; private readonly IOptions _globalSettings; private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IOptions _uSupportSettings; - private readonly ITempDataProvider _tempDataProvider; - private readonly ILogger _logger; - public uSupportSettingsService(IEmailSender emailSender, - ITempDataProvider tempDataProvider, + + + public uSupportSettingsService(ILogger logger, + IEmailSender emailSender, + IEventAggregator eventAggregator, IRazorViewEngine razorViewEngine, - ILogger logger, + ITempDataProvider tempDataProvider, IHostEnvironment hostingEnvironment, - IHttpContextAccessor httpContextAccessor, + IWebHostEnvironment webHostEnvironment, IOptions globalSettings, + IHttpContextAccessor httpContextAccessor, IOptions uSupportSettings) { + _logger = logger; + _emailSender = emailSender; + _eventAggregator = eventAggregator; + _razorViewEngine = razorViewEngine; _tempDataProvider = tempDataProvider; + _webHostEnvironment = webHostEnvironment; _globalSettings = globalSettings; - _uSupportSettings = uSupportSettings; _httpContextAccessor = httpContextAccessor; - _razorViewEngine = razorViewEngine; - _emailSender = emailSender; - _logger = logger; + _uSupportSettings = uSupportSettings; _defaultSettings = new uSupportSettingsTicket(); } public bool GetSendEmailOnTicketCreatedSetting() => _uSupportSettings.Value.Tickets.SendEmailOnTicketCreated; + public bool GetSendEmailOnTicketCommentSetting() => _uSupportSettings.Value.Tickets.SendEmailOnTicketComment; public string GetTicketUpdateEmailSetting() => _uSupportSettings.Value.Tickets.TicketUpdateEmail; public string GetEmailSubjectNewTicket(uSupportTicket? ticket = null) @@ -128,8 +146,11 @@ public async void SendEmail(string toAddress, string subject, string templateVie true); } + if (model is uSupportTicket ticket) + _eventAggregator.Publish(new EmailSendingNotification(ticket.Id, toAddress, subject, templateViewPath)); - await _emailSender.SendAsync(message, emailType: "Contact"); + + await _emailSender.SendAsync(message, emailType: "Contact"); } catch (Exception ex) { @@ -142,15 +163,24 @@ public async Task RenderEmailTemplateAsync(string templateViewPath, obje if (string.IsNullOrEmpty(templateViewPath)) throw new Exception("Failed to find email template."); - if (!templateViewPath.EndsWith(".cshtml")) + if (!templateViewPath.EndsWith(".cshtml", StringComparison.OrdinalIgnoreCase)) throw new Exception("Template file must end with '.cshtml'"); - ActionContext actionContext = new(_httpContextAccessor.HttpContext, new Microsoft.AspNetCore.Routing.RouteData(), new ActionDescriptor()); + if(_httpContextAccessor.HttpContext == null) + throw new Exception("HttpContext is null"); + + ActionContext actionContext = new(_httpContextAccessor.HttpContext, new Microsoft.AspNetCore.Routing.RouteData(), new ActionDescriptor()); using (StringWriter stringWriter = new()) { - ViewEngineResult viewResult = _razorViewEngine.GetView(templateViewPath, templateViewPath, false); + ViewEngineResult viewResult = _razorViewEngine.GetView(null, templateViewPath, false); + + if (!viewResult.Success) + { + var searchedLocations = string.Join(", ", viewResult.SearchedLocations ?? []); + throw new Exception($"Failed to find template at '{templateViewPath}'. Searched locations: {searchedLocations}"); + } - ViewDataDictionary viewData = new(new EmptyModelMetadataProvider(), new ModelStateDictionary()) + ViewDataDictionary viewData = new(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model }; @@ -166,5 +196,5 @@ public async Task RenderEmailTemplateAsync(string templateViewPath, obje return stringWriter.ToString(); } } - } -} \ No newline at end of file + } +} diff --git a/src/uSupport/Services/uSupportTicketService.cs b/src/uSupport/Services/uSupportTicketService.cs index 7c17c1e..7998411 100644 --- a/src/uSupport/Services/uSupportTicketService.cs +++ b/src/uSupport/Services/uSupportTicketService.cs @@ -82,7 +82,7 @@ public uSupportPage GetPagedActiveTickets(long page, string? sea } else { - sql.OrderBy("LastUpdated DESC"); + sql.OrderBy("LastUpdated DESC"); } var ticketCount = context.Scope.Database.Fetch(sqlCount).FirstOrDefault(); @@ -188,7 +188,6 @@ public override uSupportTicket Create(uSupportTicketSchema dto) var ticket = base.Create(dto); _eventAggregator.Publish(new CreateTicketNotification(ticket)); - _eventAggregator.Publish(new TicketHistoryNotification(dto.AuthorId, null, ticket)); return ticket; } diff --git a/src/uSupport/wwwroot/templates/NewTicketEmail.cshtml b/src/uSupport/Views/Partials/uSupport/Emails/NewTicketEmail.cshtml similarity index 96% rename from src/uSupport/wwwroot/templates/NewTicketEmail.cshtml rename to src/uSupport/Views/Partials/uSupport/Emails/NewTicketEmail.cshtml index fe061ad..6d9b2a9 100644 --- a/src/uSupport/wwwroot/templates/NewTicketEmail.cshtml +++ b/src/uSupport/Views/Partials/uSupport/Emails/NewTicketEmail.cshtml @@ -1,4 +1,4 @@ -@using uSupport.Extensions +@using uSupport.Extensions @inherits uSupportTemplate @{ var baseUrl = GetBaseUrl(Context.Request); @@ -45,7 +45,7 @@

Summary

-

@Model.Summary

+

@Html.Raw(Model.Summary)


@@ -56,4 +56,4 @@ - \ No newline at end of file + diff --git a/src/uSupport/wwwroot/templates/UpdateTicketEmail.cshtml b/src/uSupport/Views/Partials/uSupport/Emails/UpdateTicketEmail.cshtml similarity index 70% rename from src/uSupport/wwwroot/templates/UpdateTicketEmail.cshtml rename to src/uSupport/Views/Partials/uSupport/Emails/UpdateTicketEmail.cshtml index be6e8d1..65f2ecb 100644 --- a/src/uSupport/wwwroot/templates/UpdateTicketEmail.cshtml +++ b/src/uSupport/Views/Partials/uSupport/Emails/UpdateTicketEmail.cshtml @@ -1,4 +1,4 @@ -@using uSupport.Extensions +@using uSupport.Extensions @inherits uSupportTemplate @{ var baseUrl = GetBaseUrl(Context.Request); @@ -45,7 +45,7 @@

Summary

-

@Model.Summary

+

@Html.Raw(Model.Summary)


@@ -55,37 +55,39 @@ @if (Model.Comments != null && Model.Comments.Count() > 1) {
+ + + + @foreach (var comment in Model.Comments) + { + var isLast = comment.Id == Model.Comments.LastOrDefault()?.Id; + + + + + } + +
+ + + + + +
+ profile picture + + @comment.User?.Name
+ + @comment.Date.ToString("yyyy-MM-dd") + +
+
+

+ @comment.Comment +

+
} - - - @foreach (var comment in Model.Comments) - { - - - - - } - -
- - - - - -
- profile picture - - @comment.User?.Name
- - @comment.Date.ToString("yyyy-MM-dd") - -
-
-

- @comment.Comment -

-

@@ -103,4 +105,4 @@ - \ No newline at end of file + diff --git a/src/uSupport/uSupport.csproj b/src/uSupport/uSupport.csproj index 5fe46a2..5b7bedf 100644 --- a/src/uSupport/uSupport.csproj +++ b/src/uSupport/uSupport.csproj @@ -1,10 +1,11 @@  - + net8.0 App_Plugins/uSupport + true enable - enable + enable @@ -62,5 +63,5 @@ - + diff --git a/src/uSupport/wwwroot/backoffice/settings/settings.overview.controller.js b/src/uSupport/wwwroot/backoffice/settings/settings.overview.controller.js index 65091f5..d38efd6 100644 --- a/src/uSupport/wwwroot/backoffice/settings/settings.overview.controller.js +++ b/src/uSupport/wwwroot/backoffice/settings/settings.overview.controller.js @@ -14,8 +14,8 @@ TicketUpdateEmail: "None", EmailSubjectNewTicket: "A new ticket has been created", EmailSubjectUpdateTicket: "Your ticket has been updated", - EmailTemplateNewTicketPath: "/App_Plugins/uSupport/templates/NewTicketEmail.cshtml", - EmailTemplateUpdateTicketPath: "/App_Plugins/uSupport/templates/UpdateTicketEmail.cshtml", + EmailTemplateNewTicketPath: "/Views/uSupport/Emails/NewTicketEmail.cshtml", + EmailTemplateUpdateTicketPath: "/Views/uSupport/Emails/UpdateTicketEmail.cshtml", } } } @@ -38,4 +38,4 @@ vm.emailTemplateNewTicketPath = promises.getEmailTemplateNewTicketPath; vm.emailTemplateUpdateTicketPath = promises.getEmailTemplateUpdateTicketPath; }); -}); \ No newline at end of file +}); diff --git a/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.controller.js b/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.controller.js index 0265ec1..86bc2b8 100644 --- a/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.controller.js +++ b/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.controller.js @@ -1,8 +1,24 @@ -angular.module("umbraco").controller("uSupport.history.contentApp.controller", function ($scope) { +angular.module("umbraco").controller("uSupport.history.contentApp.controller", function ($scope, uSupportTicketResources) { 'use strict'; var vm = this; + vm.history = $scope.model.history.Items; + vm.pagination = { + pageNumber: 1, + totalPages: $scope.model.history.TotalPages + }; + + vm.loadHistory = function (pageNumber) { + uSupportTicketResources.getPagedHistoryByTicketId($scope.model.ticket.Id, pageNumber).then(function (history) { + vm.history = history.Items; + vm.pagination = { + pageNumber: pageNumber, + totalPages: history.TotalPages + }; + }); + }; + vm.getStatusName = function (guid) { return $scope.model.statuses.find(function (s) { return s.Id === guid; @@ -22,7 +38,7 @@ return 'secondary'; } else if (type === 'update' || type === 'updated') { return 'gray'; - } else if (type === 'resolve' || type === 'resolved') { + } else if (type === 'comment' || type === 'resolved') { return 'success'; } }; diff --git a/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.html b/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.html index 60a48d0..5a25e2b 100644 --- a/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.html +++ b/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.html @@ -6,18 +6,18 @@
-
+
-
Admin
+
{{item.User ? item.User.name : 'System'}}
{{item.Date | date:'yyyy-MM-dd HH:mm'}}
@@ -27,9 +27,12 @@ class="history-item__badge"> {{item.ActionType}} - +
+
+ to: {{change.New}} +
Status: {{vm.getStatusName(change.Old)}}{{vm.getStatusName(change.New)}} @@ -47,6 +50,15 @@
+ + +
diff --git a/src/uSupport/wwwroot/backoffice/tickets/apps/ticket/ticket.html b/src/uSupport/wwwroot/backoffice/tickets/apps/ticket/ticket.html index 4b38833..c94757c 100644 --- a/src/uSupport/wwwroot/backoffice/tickets/apps/ticket/ticket.html +++ b/src/uSupport/wwwroot/backoffice/tickets/apps/ticket/ticket.html @@ -16,7 +16,7 @@
- + diff --git a/src/uSupport/wwwroot/backoffice/tickets/tickets.edit.controller.js b/src/uSupport/wwwroot/backoffice/tickets/tickets.edit.controller.js index fd40613..04a62d4 100644 --- a/src/uSupport/wwwroot/backoffice/tickets/tickets.edit.controller.js +++ b/src/uSupport/wwwroot/backoffice/tickets/tickets.edit.controller.js @@ -34,7 +34,7 @@ vm.ticket = ticket; $q.all({ user: userService.getCurrentUser(), - history: uSupportTicketResources.getTicketHistory(ticket.Id), + history: uSupportTicketResources.getPagedHistoryByTicketId(ticket.Id, 0), statuses: uSupportTicketStatusResources.getAllTicketStatuses(), types: uSupportTicketTypeResources.getAllTicketTypes(), getChildActions: uSupportHelperServices.getChildActions("tickets", "-1", ticket.Id) @@ -61,7 +61,7 @@ vm.history = promises.history; - if (vm.history.length) { + if (vm.history.Items.length) { vm.navigation.push({ name: "History", alias: "history", From 65ba70a110aa62af40373b62f7e509338c304177 Mon Sep 17 00:00:00 2001 From: Johannes Lantz Date: Sat, 14 Mar 2026 20:04:31 +0100 Subject: [PATCH 3/8] Fixed default pathing for email templates Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../backoffice/settings/settings.overview.controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uSupport/wwwroot/backoffice/settings/settings.overview.controller.js b/src/uSupport/wwwroot/backoffice/settings/settings.overview.controller.js index d38efd6..45bfbf1 100644 --- a/src/uSupport/wwwroot/backoffice/settings/settings.overview.controller.js +++ b/src/uSupport/wwwroot/backoffice/settings/settings.overview.controller.js @@ -14,8 +14,8 @@ TicketUpdateEmail: "None", EmailSubjectNewTicket: "A new ticket has been created", EmailSubjectUpdateTicket: "Your ticket has been updated", - EmailTemplateNewTicketPath: "/Views/uSupport/Emails/NewTicketEmail.cshtml", - EmailTemplateUpdateTicketPath: "/Views/uSupport/Emails/UpdateTicketEmail.cshtml", + EmailTemplateNewTicketPath: "/Views/Partials/uSupport/Emails/NewTicketEmail.cshtml", + EmailTemplateUpdateTicketPath: "/Views/Partials/uSupport/Emails/UpdateTicketEmail.cshtml", } } } From d054c70c3e3acb9b1a997a773350e225827ef4e5 Mon Sep 17 00:00:00 2001 From: Johannes Lantz Date: Sat, 14 Mar 2026 20:06:01 +0100 Subject: [PATCH 4/8] Removed unused services Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/uSupport/Services/uSupportSettingsService.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/uSupport/Services/uSupportSettingsService.cs b/src/uSupport/Services/uSupportSettingsService.cs index 93ce518..6dcf9e1 100644 --- a/src/uSupport/Services/uSupportSettingsService.cs +++ b/src/uSupport/Services/uSupportSettingsService.cs @@ -5,11 +5,9 @@ using Umbraco.Cms.Core.Events; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using uSupport.Services.Interfaces; -using Microsoft.AspNetCore.Hosting; using Umbraco.Cms.Core.Models.Email; using Microsoft.AspNetCore.Mvc.Razor; using uSupport.Notifications.Tickets; @@ -35,7 +33,6 @@ public class uSupportSettingsService : IuSupportSettingsService private readonly IEventAggregator _eventAggregator; private readonly IRazorViewEngine _razorViewEngine; private readonly ITempDataProvider _tempDataProvider; - private readonly IWebHostEnvironment _webHostEnvironment; private readonly IOptions _globalSettings; private readonly IHttpContextAccessor _httpContextAccessor; @@ -47,8 +44,6 @@ public uSupportSettingsService(ILogger logger, IEventAggregator eventAggregator, IRazorViewEngine razorViewEngine, ITempDataProvider tempDataProvider, - IHostEnvironment hostingEnvironment, - IWebHostEnvironment webHostEnvironment, IOptions globalSettings, IHttpContextAccessor httpContextAccessor, IOptions uSupportSettings) @@ -58,7 +53,6 @@ public uSupportSettingsService(ILogger logger, _eventAggregator = eventAggregator; _razorViewEngine = razorViewEngine; _tempDataProvider = tempDataProvider; - _webHostEnvironment = webHostEnvironment; _globalSettings = globalSettings; _httpContextAccessor = httpContextAccessor; _uSupportSettings = uSupportSettings; From 0c1d408b8f36b4b907fa920dfc8f0048af58bd53 Mon Sep 17 00:00:00 2001 From: Johannes Lantz Date: Sat, 14 Mar 2026 20:07:06 +0100 Subject: [PATCH 5/8] Removed unwanted namespace Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/uSupport/Services/uSupportTicketHistoryService.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/uSupport/Services/uSupportTicketHistoryService.cs b/src/uSupport/Services/uSupportTicketHistoryService.cs index d28fb70..a8a5fdf 100644 --- a/src/uSupport/Services/uSupportTicketHistoryService.cs +++ b/src/uSupport/Services/uSupportTicketHistoryService.cs @@ -8,7 +8,6 @@ using uSupport.Services.Interfaces; using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Infrastructure.Scoping; -using Org.BouncyCastle.Utilities.Collections; using Umbraco.Cms.Core.Models.ContentEditing; using static uSupport.Helpers.uSupportPageHelper; using static uSupport.Constants.uSupportConstants; From d63a2ec670f963519e492b330553f38a2744d6ef Mon Sep 17 00:00:00 2001 From: Johannes Lantz Date: Sat, 14 Mar 2026 20:50:45 +0100 Subject: [PATCH 6/8] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../wwwroot/backoffice/tickets/tickets.edit.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uSupport/wwwroot/backoffice/tickets/tickets.edit.controller.js b/src/uSupport/wwwroot/backoffice/tickets/tickets.edit.controller.js index 04a62d4..ee8f3f5 100644 --- a/src/uSupport/wwwroot/backoffice/tickets/tickets.edit.controller.js +++ b/src/uSupport/wwwroot/backoffice/tickets/tickets.edit.controller.js @@ -34,7 +34,7 @@ vm.ticket = ticket; $q.all({ user: userService.getCurrentUser(), - history: uSupportTicketResources.getPagedHistoryByTicketId(ticket.Id, 0), + history: uSupportTicketResources.getPagedHistoryByTicketId(ticket.Id, 1), statuses: uSupportTicketStatusResources.getAllTicketStatuses(), types: uSupportTicketTypeResources.getAllTicketTypes(), getChildActions: uSupportHelperServices.getChildActions("tickets", "-1", ticket.Id) From fa56833d09d236c011b671350236798236bf702f Mon Sep 17 00:00:00 2001 From: Johannes Lantz Date: Sat, 14 Mar 2026 21:27:44 +0100 Subject: [PATCH 7/8] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../backoffice/tickets/apps/history/history.controller.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.controller.js b/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.controller.js index 86bc2b8..3c298fb 100644 --- a/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.controller.js +++ b/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.controller.js @@ -40,6 +40,11 @@ return 'gray'; } else if (type === 'comment' || type === 'resolved') { return 'success'; + } else if (type === 'sentemail') { + return 'secondary'; } + + // Fallback for any unknown or newly added action types + return 'secondary'; }; }); \ No newline at end of file From f156e018f93f5dd2ceb25d29ffb5342f2dcff363 Mon Sep 17 00:00:00 2001 From: Johannes Lantz Date: Sat, 14 Mar 2026 21:29:00 +0100 Subject: [PATCH 8/8] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../wwwroot/backoffice/tickets/apps/history/history.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.html b/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.html index 5a25e2b..eb184bb 100644 --- a/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.html +++ b/src/uSupport/wwwroot/backoffice/tickets/apps/history/history.html @@ -12,8 +12,8 @@ + img-src="{{item.User && item.User.avatars ? item.User.avatars[0] : ''}}" + img-srcset="{{item.User && item.User.avatars ? (item.User.avatars[1] + ' 2x, ' + item.User.avatars[2] + ' 3x') : ''}}">