diff --git a/src/Fusion.Resources.Functions.Common/ApiClients/ApiModels/Notifications.cs b/src/Fusion.Resources.Functions.Common/ApiClients/ApiModels/Notifications.cs index 3aefcb3ca..0395c5d64 100644 --- a/src/Fusion.Resources.Functions.Common/ApiClients/ApiModels/Notifications.cs +++ b/src/Fusion.Resources.Functions.Common/ApiClients/ApiModels/Notifications.cs @@ -7,9 +7,11 @@ public class SendNotificationsRequest { [JsonProperty("emailPriority")] public int EmailPriority { get; set; } - [JsonProperty("title")] public string Title { get; set; } + [JsonProperty("title")] public string? Title { get; set; } - [JsonProperty("description")] public string Description { get; set; } + [JsonProperty("description")] public string? Description { get; set; } - [JsonProperty("card")] public AdaptiveCard Card { get; set; } + [JsonProperty("appKey")] public string? AppKey { get; set; } + + [JsonProperty("card")] public AdaptiveCard? Card { get; set; } } diff --git a/src/Fusion.Summary.Functions/CardBuilder/AdaptiveCardBuilder.cs b/src/Fusion.Summary.Functions/CardBuilder/AdaptiveCardBuilder.cs index ed2250325..464e2df62 100644 --- a/src/Fusion.Summary.Functions/CardBuilder/AdaptiveCardBuilder.cs +++ b/src/Fusion.Summary.Functions/CardBuilder/AdaptiveCardBuilder.cs @@ -7,7 +7,7 @@ namespace Fusion.Summary.Functions.CardBuilder; public class AdaptiveCardBuilder { - private readonly AdaptiveCard _adaptiveCard = new(new AdaptiveSchemaVersion(1, 0)); + private readonly AdaptiveCard _adaptiveCard = new(new AdaptiveSchemaVersion(1, 2)); public AdaptiveCardBuilder AddHeading(string text) { @@ -24,14 +24,30 @@ public AdaptiveCardBuilder AddHeading(string text) return this; } - public AdaptiveCardBuilder AddColumnSet(params AdaptiveCardColumn[] columns) + public AdaptiveCardBuilder AddTextRow(string valueText, string headerText, string customText = "") { - var columnSet = new AdaptiveColumnSet + var container = new AdaptiveContainer() { - Columns = columns.Select(col => col.Column).ToList(), - Separator = true + Separator = true, + Items = new List() + { + new AdaptiveTextBlock + { + Text = $"{valueText} {customText}", + Wrap = true, + HorizontalAlignment = AdaptiveHorizontalAlignment.Center, + Size = AdaptiveTextSize.ExtraLarge + }, + new AdaptiveTextBlock + { + Text = headerText, + Wrap = true, + HorizontalAlignment = AdaptiveHorizontalAlignment.Center + } + } }; - _adaptiveCard.Body.Add(columnSet); + + _adaptiveCard.Body.Add(container); return this; } @@ -41,31 +57,45 @@ public AdaptiveCardBuilder AddListContainer(string headerText, var listContainer = new AdaptiveContainer { Separator = true, - Items = new List + }; + + var header = new AdaptiveTextBlock + { + Weight = AdaptiveTextWeight.Bolder, + Text = headerText, + Wrap = true, + Size = AdaptiveTextSize.Large, + HorizontalAlignment = AdaptiveHorizontalAlignment.Center + }; + + var rows = new List(); + + foreach (var listObject in objectLists) + { + var row = new AdaptiveColumnSet() { - new AdaptiveTextBlock + Columns = listObject.Select(o => new AdaptiveColumn() { - Weight = AdaptiveTextWeight.Bolder, - Text = headerText, - Wrap = true, - Size = AdaptiveTextSize.Large - }, - new AdaptiveColumnSet - { - Columns = new List + Width = AdaptiveColumnWidth.Stretch, + Items = new List { - new() + new AdaptiveTextBlock { - Width = AdaptiveColumnWidth.Stretch, - Items = new List - { - new AdaptiveCardList(objectLists).List - } + Text = o.Value, + Wrap = true, + HorizontalAlignment = o.Alignment } } - } - } - }; + }).ToList() + }; + + rows.Add(row); + } + + listContainer.Items.Add(header); + listContainer.Items.AddRange(rows); + + _adaptiveCard.Body.Add(listContainer); return this; } @@ -100,76 +130,6 @@ public AdaptiveCard Build() return _adaptiveCard; } - public class AdaptiveCardColumn - { - public AdaptiveColumn Column { get; } - - public AdaptiveCardColumn(string numberText, string headerText, string customText = "") - { - Column = new AdaptiveColumn - { - Width = AdaptiveColumnWidth.Stretch, - Separator = true, - Spacing = AdaptiveSpacing.Medium, - Items = new List - { - new AdaptiveTextBlock - { - Text = $"{numberText} {customText}", - Wrap = true, - HorizontalAlignment = AdaptiveHorizontalAlignment.Center, - Size = AdaptiveTextSize.ExtraLarge - }, - new AdaptiveTextBlock - { - Text = headerText, - Wrap = true, - HorizontalAlignment = AdaptiveHorizontalAlignment.Center - } - } - }; - } - } - - private class AdaptiveCardList - { - public AdaptiveContainer List { get; } - - public AdaptiveCardList(List> objectLists) - { - var listItems = new List(); - foreach (var objects in objectLists) - { - var columns = new List(); - foreach (var o in objects) - { - var column = new AdaptiveColumn() - { - Width = AdaptiveColumnWidth.Stretch, - Items = new List - { - new AdaptiveTextBlock - { - Text = $"{o.Value} ", Wrap = true, - HorizontalAlignment = o.Alignment - } - } - }; - columns.Add(column); - } - - listItems.Add(new AdaptiveColumnSet() - { - Columns = columns - }); - } - - List = new AdaptiveContainer - { - Items = listItems - }; - } - } public class ListObject { diff --git a/src/Fusion.Summary.Functions/Functions/WeeklyDepartmentSummarySender.cs b/src/Fusion.Summary.Functions/Functions/WeeklyDepartmentSummarySender.cs index ec3d874a3..6e23e5ec0 100644 --- a/src/Fusion.Summary.Functions/Functions/WeeklyDepartmentSummarySender.cs +++ b/src/Fusion.Summary.Functions/Functions/WeeklyDepartmentSummarySender.cs @@ -127,37 +127,36 @@ private SendNotificationsRequest CreateNotification(ApiWeeklySummaryReport repor var card = new AdaptiveCardBuilder() .AddHeading($"**Weekly summary - {department.FullDepartmentName}**") - .AddColumnSet(new AdaptiveCardColumn( + .AddTextRow( report.NumberOfPersonnel, - "Number of personnel (employees and external hire)")) - .AddColumnSet(new AdaptiveCardColumn( + "Number of personnel (employees and external hire)") + .AddTextRow( report.CapacityInUse, "Capacity in use", - "%")) - .AddColumnSet( - new AdaptiveCardColumn( + "%") + .AddTextRow( report.NumberOfRequestsLastPeriod, - "New requests last week")) - .AddColumnSet(new AdaptiveCardColumn( + "New requests last week") + .AddTextRow( report.NumberOfOpenRequests, - "Open requests")) - .AddColumnSet(new AdaptiveCardColumn( + "Open requests") + .AddTextRow( report.NumberOfRequestsStartingInLessThanThreeMonths, - "Requests with start date < 3 months")) - .AddColumnSet(new AdaptiveCardColumn( + "Requests with start date < 3 months") + .AddTextRow( report.NumberOfRequestsStartingInMoreThanThreeMonths, - "Requests with start date > 3 months")) - .AddColumnSet(new AdaptiveCardColumn( + "Requests with start date > 3 months") + .AddTextRow( averageTimeToHandleRequests > 0 ? averageTimeToHandleRequests + " day(s)" : "Less than a day", - "Average time to handle request (last 12 months)")) - .AddColumnSet(new AdaptiveCardColumn( + "Average time to handle request (last 12 months)") + .AddTextRow( report.AllocationChangesAwaitingTaskOwnerAction, - "Allocation changes awaiting task owner action")) - .AddColumnSet(new AdaptiveCardColumn( + "Allocation changes awaiting task owner action") + .AddTextRow( report.ProjectChangesAffectingNextThreeMonths, - "Project changes last week affecting next 3 months")) + "Project changes last week affecting next 3 months") .AddListContainer("Allocations ending soon with no future allocation:", endingPositionsObjectList) .AddListContainer("Personnel with more than 100% workload:", personnelMoreThan100PercentObjectList) .AddNewLine() @@ -170,6 +169,7 @@ private SendNotificationsRequest CreateNotification(ApiWeeklySummaryReport repor Title = $"Weekly summary - {department.FullDepartmentName}", EmailPriority = 1, Card = card, + AppKey = "personnel-allocation", Description = $"Weekly report for department - {department.FullDepartmentName}" }; } diff --git a/src/backend/function/Fusion.Resources.Functions/Functions/Notifications/AdaptiveCardBuilder.cs b/src/backend/function/Fusion.Resources.Functions/Functions/Notifications/AdaptiveCardBuilder.cs index 9689ce4ef..746af9381 100644 --- a/src/backend/function/Fusion.Resources.Functions/Functions/Notifications/AdaptiveCardBuilder.cs +++ b/src/backend/function/Fusion.Resources.Functions/Functions/Notifications/AdaptiveCardBuilder.cs @@ -7,7 +7,7 @@ namespace Fusion.Resources.Functions.Functions.Notifications; public class AdaptiveCardBuilder { - private readonly AdaptiveCard _adaptiveCard = new(new AdaptiveSchemaVersion(1, 0)); + private readonly AdaptiveCard _adaptiveCard = new(new AdaptiveSchemaVersion(1, 2)); public AdaptiveCardBuilder AddHeading(string text) { @@ -18,53 +18,84 @@ public AdaptiveCardBuilder AddHeading(string text) HorizontalAlignment = AdaptiveHorizontalAlignment.Center, Separator = true, Size = AdaptiveTextSize.Large, - Weight = AdaptiveTextWeight.Bolder, + Weight = AdaptiveTextWeight.Bolder }; _adaptiveCard.Body.Add(heading); return this; } - public AdaptiveCardBuilder AddColumnSet(params AdaptiveCardColumn[] columns) + public AdaptiveCardBuilder AddTextRow(string valueText, string headerText, string customText = "") { - var columnSet = new AdaptiveColumnSet + var container = new AdaptiveContainer() { - Columns = columns.Select(col => col.Column).ToList(), - Separator = true + Separator = true, + Items = new List() + { + new AdaptiveTextBlock + { + Text = $"{valueText} {customText}", + Wrap = true, + HorizontalAlignment = AdaptiveHorizontalAlignment.Center, + Size = AdaptiveTextSize.ExtraLarge + }, + new AdaptiveTextBlock + { + Text = headerText, + Wrap = true, + HorizontalAlignment = AdaptiveHorizontalAlignment.Center + } + } }; - _adaptiveCard.Body.Add(columnSet); + + _adaptiveCard.Body.Add(container); return this; } - public AdaptiveCardBuilder AddListContainer(string headerText, List> objectLists) + public AdaptiveCardBuilder AddListContainer(string headerText, + List> objectLists) { var listContainer = new AdaptiveContainer { Separator = true, - Items = new List + }; + + var header = new AdaptiveTextBlock + { + Weight = AdaptiveTextWeight.Bolder, + Text = headerText, + Wrap = true, + Size = AdaptiveTextSize.Large, + HorizontalAlignment = AdaptiveHorizontalAlignment.Center + }; + + var rows = new List(); + + foreach (var listObject in objectLists) + { + var row = new AdaptiveColumnSet() { - new AdaptiveTextBlock - { - Weight = AdaptiveTextWeight.Bolder, - Text = headerText, - Wrap = true, - Size = AdaptiveTextSize.Large, - }, - new AdaptiveColumnSet + Columns = listObject.Select(o => new AdaptiveColumn() { - Columns = new List + Width = AdaptiveColumnWidth.Stretch, + Items = new List { - new() + new AdaptiveTextBlock { - Width = AdaptiveColumnWidth.Stretch, - Items = new List - { - new AdaptiveCardList(objectLists).List - } + Text = o.Value, + Wrap = true, + HorizontalAlignment = o.Alignment } } - } - } - }; + }).ToList() + }; + + rows.Add(row); + } + + listContainer.Items.Add(header); + listContainer.Items.AddRange(rows); + + _adaptiveCard.Body.Add(listContainer); return this; } @@ -86,7 +117,7 @@ public AdaptiveCardBuilder AddNewLine() { var container = new AdaptiveContainer() { - Separator = true, + Separator = true }; _adaptiveCard.Body.Add(container); @@ -99,80 +130,10 @@ public AdaptiveCard Build() return _adaptiveCard; } - public class AdaptiveCardColumn - { - public AdaptiveColumn Column { get; } - - public AdaptiveCardColumn(string numberText, string headerText, string? customText = null) - { - Column = new AdaptiveColumn - { - Width = AdaptiveColumnWidth.Stretch, - Separator = true, - Spacing = AdaptiveSpacing.Medium, - Items = new List - { - new AdaptiveTextBlock - { - Text = $"{numberText} {customText ?? ""}", - Wrap = true, - HorizontalAlignment = AdaptiveHorizontalAlignment.Center, - Size = AdaptiveTextSize.ExtraLarge - }, - new AdaptiveTextBlock - { - Text = headerText, - Wrap = true, - HorizontalAlignment = AdaptiveHorizontalAlignment.Center - } - } - }; - } - } - private class AdaptiveCardList + public class ListObject { - public AdaptiveContainer List { get; } - - public AdaptiveCardList(List> objectLists) - { - var listItems = new List(); - foreach (var objects in objectLists) - { - var columns = new List(); - foreach (var o in objects) - { - var column = new AdaptiveColumn() - { - Width = AdaptiveColumnWidth.Stretch, - Items = new List - { - new AdaptiveTextBlock - { - Text = $"{o.Value} ", Wrap = true, - HorizontalAlignment = o.Alignment - }, - } - }; - columns.Add(column); - } - - listItems.Add(new AdaptiveColumnSet() - { - Columns = columns - }); - } - - List = new AdaptiveContainer - { - Items = listItems - }; - } + public string Value { get; set; } + public AdaptiveHorizontalAlignment Alignment { get; set; } } -} - -public class ListObject -{ - public string Value { get; set; } - public AdaptiveHorizontalAlignment Alignment { get; set; } } \ No newline at end of file diff --git a/src/backend/function/Fusion.Resources.Functions/Functions/Notifications/ResourceOwner/WeeklyReport/ScheduledReportContentBuilderFunction.cs b/src/backend/function/Fusion.Resources.Functions/Functions/Notifications/ResourceOwner/WeeklyReport/ScheduledReportContentBuilderFunction.cs index d803ae957..8783ea52d 100644 --- a/src/backend/function/Fusion.Resources.Functions/Functions/Notifications/ResourceOwner/WeeklyReport/ScheduledReportContentBuilderFunction.cs +++ b/src/backend/function/Fusion.Resources.Functions/Functions/Notifications/ResourceOwner/WeeklyReport/ScheduledReportContentBuilderFunction.cs @@ -209,37 +209,36 @@ private AdaptiveCard CreateResourceOwnerAdaptiveCard( var averageTimeToHandleRequests = ResourceOwnerReportDataCreator.GetAverageTimeToHandleRequests(requests); var card = new AdaptiveCardBuilder() .AddHeading($"**Weekly summary - {departmentIdentifier}**") - .AddColumnSet(new AdaptiveCardColumn( + .AddTextRow( ResourceOwnerReportDataCreator.GetTotalNumberOfPersonnel(personnel).ToString(), - "Number of personnel (employees and external hire)")) - .AddColumnSet(new AdaptiveCardColumn( + "Number of personnel (employees and external hire)") + .AddTextRow( ResourceOwnerReportDataCreator.GetCapacityInUse(personnel).ToString(), "Capacity in use", - "%")) - .AddColumnSet( - new AdaptiveCardColumn( + "%") + .AddTextRow( ResourceOwnerReportDataCreator.GetNumberOfRequestsLastWeek(requests).ToString(), - "New requests last week")) - .AddColumnSet(new AdaptiveCardColumn( + "New requests last week") + .AddTextRow( ResourceOwnerReportDataCreator.GetNumberOfOpenRequests(requests).ToString(), - "Open requests")) - .AddColumnSet(new AdaptiveCardColumn( + "Open requests") + .AddTextRow( ResourceOwnerReportDataCreator.GetNumberOfRequestsStartingInLessThanThreeMonths(requests).ToString(), - "Requests with start date < 3 months")) - .AddColumnSet(new AdaptiveCardColumn( + "Requests with start date < 3 months") + .AddTextRow( ResourceOwnerReportDataCreator.GetNumberOfRequestsStartingInMoreThanThreeMonths(requests).ToString(), - "Requests with start date > 3 months")) - .AddColumnSet(new AdaptiveCardColumn( + "Requests with start date > 3 months") + .AddTextRow( averageTimeToHandleRequests > 0 ? averageTimeToHandleRequests + " day(s)" : "Less than a day", - "Average time to handle request (last 12 months)")) - .AddColumnSet(new AdaptiveCardColumn( + "Average time to handle request (last 12 months)") + .AddTextRow( ResourceOwnerReportDataCreator.GetAllocationChangesAwaitingTaskOwnerAction(requests).ToString(), - "Allocation changes awaiting task owner action")) - .AddColumnSet(new AdaptiveCardColumn( + "Allocation changes awaiting task owner action") + .AddTextRow( ResourceOwnerReportDataCreator.CalculateDepartmentChangesLastWeek(personnel).ToString(), - "Project changes last week affecting next 3 months")) + "Project changes last week affecting next 3 months") .AddListContainer("Allocations ending soon with no future allocation:", endingPositionsObjectList) .AddListContainer("Personnel with more than 100% workload:", personnelMoreThan100PercentObjectList) .AddNewLine()