Beispiel #1
0
        public FontColorConfig GetForegroundColors(AdaptiveTextColor textColor)
        {
            switch (textColor)
            {
            case AdaptiveTextColor.Accent:
                return(RenderArgs.ForegroundColors.Accent);

            case AdaptiveTextColor.Attention:
                return(RenderArgs.ForegroundColors.Attention);

            case AdaptiveTextColor.Dark:
                return(RenderArgs.ForegroundColors.Dark);

            case AdaptiveTextColor.Good:
                return(RenderArgs.ForegroundColors.Good);

            case AdaptiveTextColor.Light:
                return(RenderArgs.ForegroundColors.Light);

            case AdaptiveTextColor.Warning:
                return(RenderArgs.ForegroundColors.Warning);

            case AdaptiveTextColor.Default:
            default:
                return(RenderArgs.ForegroundColors.Default);
            }
        }
        public static void SetColor(this Span inlineRun, AdaptiveTextColor color, bool isSubtle, AdaptiveRenderContext context)
        {
            FontColorConfig colorOption = context.GetForegroundColors(color);
            string          colorCode   = isSubtle ? colorOption.Subtle : colorOption.Default;

            inlineRun.Foreground = context.GetColorBrush(colorCode);
        }
        /// <summary>
        /// Method to send goal reminder card to personal bot.
        /// </summary>
        /// <param name="personalGoalDetail">Holds personal goal detail entity data sent from background service.</param>
        /// <param name="isReminderBeforeThreeDays">Determines reminder to be sent prior 3 days to end date.</param>
        /// <returns>A Task represents goal reminder card is sent to the bot, installed in the personal scope.</returns>
        public async Task SendGoalReminderToPersonalBotAsync(PersonalGoalDetail personalGoalDetail, bool isReminderBeforeThreeDays = false)
        {
            personalGoalDetail = personalGoalDetail ?? throw new ArgumentNullException(nameof(personalGoalDetail));
            var conversationReference = new ConversationReference()
            {
                ChannelId = Constants.TeamsBotFrameworkChannelId,
                Bot       = new ChannelAccount()
                {
                    Id = $"28:{this.microsoftAppCredentials.MicrosoftAppId}"
                },
                ServiceUrl   = personalGoalDetail.ServiceUrl,
                Conversation = new ConversationAccount()
                {
                    ConversationType = Constants.PersonalConversationType, Id = personalGoalDetail.ConversationId, TenantId = this.options.Value.TenantId
                },
            };

            try
            {
                await this.retryPolicy.ExecuteAsync(async() =>
                {
                    await((BotFrameworkAdapter)this.adapter).ContinueConversationAsync(
                        this.microsoftAppCredentials.MicrosoftAppId,
                        conversationReference,
                        async(turnContext, cancellationToken) =>
                    {
                        string reminderType = string.Empty;
                        AdaptiveTextColor reminderTypeColor = AdaptiveTextColor.Accent;
                        if (isReminderBeforeThreeDays)
                        {
                            reminderType      = this.localizer.GetString("PersonalGoalEndingAfterThreeDays");
                            reminderTypeColor = AdaptiveTextColor.Attention;
                        }
                        else
                        {
                            reminderType = this.GetReminderTypeString(personalGoalDetail.ReminderFrequency);
                        }

                        var goalReminderAttachment = MessageFactory.Attachment(GoalReminderCard.GetGoalReminderCard(this.localizer, this.options.Value.ManifestId, this.options.Value.GoalsTabEntityId, reminderType, reminderTypeColor));
                        this.logger.LogInformation($"Sending goal reminder card to Personal bot. Conversation id: {personalGoalDetail.ConversationId}");
                        await turnContext.SendActivityAsync(goalReminderAttachment, cancellationToken);
                    },
                        CancellationToken.None);
                });
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, $"Error while sending goal reminder card to personal bot: {ex.Message} at {nameof(this.SendGoalReminderToPersonalBotAsync)}");
                throw;
            }
        }
        public string GetColor(AdaptiveTextColor color, bool isSubtle, bool isHighlight)
        {
            FontColorConfig colorConfig;

            switch (color)
            {
            case AdaptiveTextColor.Accent:
                colorConfig = RenderArgs.ForegroundColors.Accent;
                break;

            case AdaptiveTextColor.Good:
                colorConfig = RenderArgs.ForegroundColors.Good;
                break;

            case AdaptiveTextColor.Warning:
                colorConfig = RenderArgs.ForegroundColors.Warning;
                break;

            case AdaptiveTextColor.Attention:
                colorConfig = RenderArgs.ForegroundColors.Attention;
                break;

            case AdaptiveTextColor.Dark:
                colorConfig = RenderArgs.ForegroundColors.Dark;
                break;

            case AdaptiveTextColor.Light:
                colorConfig = RenderArgs.ForegroundColors.Light;
                break;

            default:
                colorConfig = RenderArgs.ForegroundColors.Default;
                break;
            }

            if (isHighlight)
            {
                return(GetRGBColor(isSubtle ? colorConfig.HighlightColors.Subtle : colorConfig.HighlightColors.Default));
            }
            else
            {
                return(GetRGBColor(isSubtle ? colorConfig.Subtle : colorConfig.Default));
            }
        }
Beispiel #5
0
        public string GetColor(AdaptiveTextColor color, bool isSubtle)
        {
            FontColorConfig colorConfig;

            switch (color)
            {
            case AdaptiveTextColor.Accent:
                colorConfig = Config.ContainerStyles.Default.ForegroundColors.Accent;
                break;

            case AdaptiveTextColor.Good:
                colorConfig = Config.ContainerStyles.Default.ForegroundColors.Good;
                break;

            case AdaptiveTextColor.Warning:
                colorConfig = Config.ContainerStyles.Default.ForegroundColors.Warning;
                break;

            case AdaptiveTextColor.Attention:
                colorConfig = Config.ContainerStyles.Default.ForegroundColors.Attention;
                break;

            case AdaptiveTextColor.Dark:
                colorConfig = Config.ContainerStyles.Default.ForegroundColors.Dark;
                break;

            case AdaptiveTextColor.Light:
                colorConfig = Config.ContainerStyles.Default.ForegroundColors.Light;
                break;

            default:
                colorConfig = Config.ContainerStyles.Default.ForegroundColors.Default;
                break;
            }
            return(GetRGBColor(isSubtle ? colorConfig.Subtle : colorConfig.Default));
        }
Beispiel #6
0
        public AdaptiveTextBlock GetadaptiveTextBlock(string InputTxt, AdaptiveTextSize Size, AdaptiveTextColor Color, AdaptiveTextWeight Weight, AdaptiveHorizontalAlignment adaptiveHorizontalAlignment)
        {
            var TextBlock = GetadaptiveTextBlock(InputTxt, Size, Weight, adaptiveHorizontalAlignment);

            TextBlock.Color = Color;
            return(TextBlock);
        }
Beispiel #7
0
        public AdaptiveTextBlock GetadaptiveTextBlock(string InputTxt, AdaptiveTextWeight Weight, AdaptiveTextColor Color)
        {
            var TextBlock = GetadaptiveTextBlock(InputTxt);

            TextBlock.Weight = Weight;
            TextBlock.Color  = Color;
            return(TextBlock);
        }
        public override AdaptiveCard GetPreviewCard()
        {
            string            broadcastType  = " ❗ EMERGENCY BROADCAST";
            AdaptiveTextColor broadcaseColor = AdaptiveTextColor.Attention;

            switch (Sensitivity)
            {
            case MessageSensitivity.Information:
                broadcastType  = " 📄 INFORMATION BROADCAST";
                broadcaseColor = AdaptiveTextColor.Good;
                break;

            case MessageSensitivity.Important:
                broadcastType  = " ❕ IMPORTANT BROADCAST";
                broadcaseColor = AdaptiveTextColor.Warning;
                break;

            default:
                break;
            }

            var previewCard = new AdaptiveCard(new AdaptiveSchemaVersion("1.0"))
            {
                Body = new List <AdaptiveElement>()
                {
                    new AdaptiveContainer()
                    {
                        Items = new List <AdaptiveElement>()
                        {
                            new AdaptiveTextBlock()
                            {
                                Id   = "sensitivity",
                                Text = broadcastType,
                                Wrap = true,
                                HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                                Spacing             = AdaptiveSpacing.None,
                                Weight   = AdaptiveTextWeight.Bolder,
                                Color    = broadcaseColor,
                                MaxLines = 1
                            }
                        }
                    },
                    new AdaptiveContainer()
                    {
                    },
                    new AdaptiveTextBlock()
                    {
                        Id     = "title",
                        Text   = Title, //  $"Giving Campaign 2018 is here",
                        Size   = AdaptiveTextSize.ExtraLarge,
                        Weight = AdaptiveTextWeight.Bolder,
                        Wrap   = true
                    },

                    new AdaptiveTextBlock()
                    {
                        Id       = "subTitle",
                        Text     = SubTitle, //  $"Have you contributed to Contoso's mission this year?",
                        Size     = AdaptiveTextSize.Medium,
                        Spacing  = AdaptiveSpacing.None,
                        Wrap     = true,
                        IsSubtle = true
                    },
                    new AdaptiveImage()
                    {
                        Id   = "bannerImage",
                        Url  = Uri.IsWellFormedUriString(ImageUrl, UriKind.Absolute)? new Uri(ImageUrl) : null,       //"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSG-vkjeuIlD-up_-VHCKgcREhFGp27lDErFkveBLQBoPZOHwMbjw"),
                        Size = AdaptiveImageSize.Stretch
                    },
                    new AdaptiveColumnSet()
                    {
                        Columns = new List <AdaptiveColumn>()
                        {
                            new AdaptiveColumn()
                            {
                                Width = AdaptiveColumnWidth.Auto,
                                Items = new List <AdaptiveElement>()
                                {
                                    // Need to fetch this from Graph API.
                                    new AdaptiveImage()
                                    {
                                        Id = "profileImage", Url = Uri.IsWellFormedUriString(Author?.ProfilePhoto, UriKind.Absolute)? new Uri(Author?.ProfilePhoto) : null, Size = AdaptiveImageSize.Small, Style = AdaptiveImageStyle.Person
                                    }                                                                                                                                                                                                                              //   new Uri("https://pbs.twimg.com/profile_images/3647943215/d7f12830b3c17a5a9e4afcc370e3a37e_400x400.jpeg"),Size=AdaptiveImageSize.Small,Style=AdaptiveImageStyle.Person
                                }
                            },
                            new AdaptiveColumn()
                            {
                                Width = AdaptiveColumnWidth.Auto,
                                Items = new List <AdaptiveElement>()
                                {
                                    new AdaptiveTextBlock()
                                    {
                                        Id     = "authorName",
                                        Text   = Author?.Name,        // "SERENA RIBEIRO",
                                        Weight = AdaptiveTextWeight.Bolder, Wrap = true
                                    },
                                    new AdaptiveTextBlock()
                                    {
                                        Id   = "authorRole",
                                        Text = Author?.Role,          //"Chief of Staff, Contoso Management",
                                        Size = AdaptiveTextSize.Small, Spacing = AdaptiveSpacing.None, IsSubtle = true, Wrap = true
                                    }
                                }
                            }
                        }
                    },
                    new AdaptiveContainer()
                    {
                        Items = new List <AdaptiveElement>()
                        {
                            new AdaptiveTextBlock()
                            {
                                Id   = "mainText",
                                Text = ShowAllDetailsButton ? Preview : Body,  // "The 2018 Employee Giving Campaign is officially underway!  Our incredibly generous culture of employee giving is unique to Contoso, and has a long history going back to our founder and his family’s core belief and value in philanthropy.   Individually and collectively, we can have an incredible impact no matter how we choose to give.  We are all very fortunate and 2018 has been a good year for the company which we are all participating in.  Having us live in a community with a strong social safety net benefits us all so lets reflect our participation in this year's success with participation in Give.",
                                Wrap = true
                            }
                        }
                    }
                },
            };

            // Image element without url does not render on phone. Remove empty images.
            AdaptiveElement adaptiveElement = previewCard.Body.FirstOrDefault(i => i.Id == "bannerImage");

            if (!Uri.IsWellFormedUriString(ImageUrl, UriKind.Absolute) && adaptiveElement != null)
            {
                previewCard.Body.Remove(adaptiveElement);
            }

            previewCard.Actions = new List <AdaptiveAction>();
            if (ShowAllDetailsButton)
            {
                previewCard.Actions.Add(new AdaptiveSubmitAction()
                {
                    Id    = "moreDetails",
                    Title = "More Details",
                    Data  = new AdaptiveCardValue <ActionDetails>()
                    {
                        Data = new AnnouncementActionDetails()
                        {
                            ActionType = Constants.ShowMoreDetails, Id = Id
                        }
                    }
                });

                if (IsAcknowledgementRequested)
                {
                    previewCard.Actions.Add(new AdaptiveSubmitAction()
                    {
                        Id    = "acknowledge",
                        Title = Constants.Acknowledge,
                        Data  = new AnnouncementActionDetails()
                        {
                            ActionType = Constants.Acknowledge, Id = Id
                        }
                    });
                }
                if (IsContactAllowed)
                {
                    previewCard.Actions.Add(new AdaptiveOpenUrlAction()
                    {
                        Id    = "contactSender",
                        Title = Constants.ContactSender,
                        Url   = new Uri($"https://teams.microsoft.com/l/chat/0/0?users={OwnerId}")
                    });
                }
            }

            return(previewCard);
        }
        private AdaptiveCard BuildCard(string mapImageUrl, string gameTypeIconUrl,
                                       string map, string gameType, AdaptiveTextColor placementColour, string placement,
                                       string stat1Name, string stat1Value, string stat2Name, string stat2Value)
        {
            var newCard = new AdaptiveCard();

            newCard.BackgroundImage = new Uri(mapImageUrl);
            newCard.Body.Add(new AdaptiveContainer()
            {
                Items =
                {
                    new AdaptiveColumnSet()
                    {
                        Height  = AdaptiveHeight.Stretch,
                        Spacing = AdaptiveSpacing.None,
                        Columns =
                        {
                            new AdaptiveColumn()
                            {
                                Spacing = AdaptiveSpacing.None,
                                Height  = AdaptiveHeight.Stretch,
                                VerticalContentAlignment = AdaptiveVerticalContentAlignment.Center,
                                Items =
                                {
                                    new AdaptiveImage()
                                    {
                                        Spacing = AdaptiveSpacing.None,
                                        Url     = new Uri(gameTypeIconUrl),
                                        Size    = AdaptiveImageSize.Small
                                    }
                                },
                                Width = "auto"
                            },
                            new AdaptiveColumn()
                            {
                                Spacing = AdaptiveSpacing.Small,
                                VerticalContentAlignment = AdaptiveVerticalContentAlignment.Center,
                                Items =
                                {
                                    new AdaptiveTextBlock()
                                    {
                                        Spacing  = AdaptiveSpacing.None,
                                        Size     = AdaptiveTextSize.ExtraLarge,
                                        Weight   = AdaptiveTextWeight.Bolder,
                                        Text     = map,
                                        Wrap     = true,
                                        MaxLines = 2
                                    },
                                    new AdaptiveColumnSet()
                                    {
                                        Spacing = AdaptiveSpacing.None,
                                        Columns =
                                        {
                                            new AdaptiveColumn()
                                            {
                                                Spacing = AdaptiveSpacing.None,
                                                Items   =
                                                {
                                                    new AdaptiveTextBlock()
                                                    {
                                                        Spacing = AdaptiveSpacing.None,
                                                        Text    = gameType
                                                    }
                                                },
                                                Width = "stretch"
                                            },
                                            new AdaptiveColumn()
                                            {
                                                Items =
                                                {
                                                    new AdaptiveTextBlock()
                                                    {
                                                        HorizontalAlignment = AdaptiveHorizontalAlignment.Right,
                                                        Weight = AdaptiveTextWeight.Bolder,
                                                        Color  = placementColour,
                                                        Text   = placement
                                                    }
                                                },
                                                Width = "auto"
                                            }
                                        }
                                    }
                                },
                                Width = "stretch"
                            }
                        }
                    },
                    new AdaptiveColumnSet()
                    {
                        Spacing = AdaptiveSpacing.Medium,
                        Height  = AdaptiveHeight.Stretch,
                        Columns =
                        {
                            new AdaptiveColumn()
                            {
                                Items =
                                {
                                    new AdaptiveTextBlock()
                                    {
                                        Size = AdaptiveTextSize.Small,
                                        Text = stat1Name
                                    },
                                    new AdaptiveTextBlock()
                                    {
                                        Spacing = AdaptiveSpacing.None,
                                        Size    = AdaptiveTextSize.Large,
                                        Weight  = AdaptiveTextWeight.Bolder,
                                        Text    = stat1Value
                                    }
                                },
                                Width = "stretch"
                            },
                            new AdaptiveColumn()
                            {
                                Items =
                                {
                                    new AdaptiveTextBlock()
                                    {
                                        Size = AdaptiveTextSize.Small,
                                        Text = stat2Name
                                    },
                                    new AdaptiveTextBlock()
                                    {
                                        Spacing = AdaptiveSpacing.None,
                                        Size    = AdaptiveTextSize.Large,
                                        Weight  = AdaptiveTextWeight.Bolder,
                                        Text    = stat2Value
                                    }
                                },
                                Width = "stretch"
                            }
                        }
                    }
                }
            });
            return(newCard);
        }
 private MsGraphUserActivity BuildActivity(string activityId, string contentUrl,
                                           string gameTypeIconUrl, string gameType, string map, DateTime startTime,
                                           DateTime endTime, string mapImageUrl, AdaptiveTextColor placementColour,
                                           string placement, string stat1Name, string stat1Value, string stat2Name, string stat2Value)
 {
     return(new MsGraphUserActivity
     {
         AppActivityId = $"/destiny2-pgcr?{activityId}",
         ActivitySourceHost = "destiny2-activity-tracker",
         AppDisplayName = "Destiny 2",
         ActivationUrl = contentUrl,
         ContentUrl = contentUrl,
         FallbackUrl = contentUrl,
         VisualElements = new MsGraphVisualElements
         {
             Attribution = new MsGraphAttribution
             {
                 IconUrl = gameTypeIconUrl,
                 AlternateText = $"{gameType} // {map}",
                 AddImageQuery = "false"
             },
             Description = $"{gameType} on {map}",
             BackgroundColor = "#000000",
             DisplayText = "Destiny 2",
             Content = BuildCard(mapImageUrl, gameTypeIconUrl, map, gameType, placementColour,
                                 placement, stat1Name, stat1Value, stat2Name, stat2Value)
         },
         HistoryItems = new List <MsGraphHistoryItem>
         {
             new MsGraphHistoryItem
             {
                 StartedDateTime = startTime,
                 LastActiveDateTime = endTime
             }
         }
     });
 }
 public static void AddTextBlockWithColumn(AdaptiveColumn column, string text, AdaptiveTextWeight TextWeight, AdaptiveTextSize size, AdaptiveTextColor TextColor, bool isSubTitle = true)
 {
     column.Items.Add(new AdaptiveTextBlock()
     {
         Text   = text,
         Weight = TextWeight,
         Size   = size,
         Color  = TextColor,
         HorizontalAlignment = AdaptiveHorizontalAlignment.Center,
         IsSubtle            = isSubTitle,
         Separation          = AdaptiveSeparationStyle.None
     });
 }
        public static AdaptiveTextBlock AddTextBlock(string value, AdaptiveTextWeight TextWeight, AdaptiveTextSize TextSize, AdaptiveTextColor TextColor)
        {
            AdaptiveTextBlock newAdaptiveTextBlock = new AdaptiveTextBlock()
            {
            };

            newAdaptiveTextBlock.Text = value;

            //newAdaptiveTextBlock.Text = "Sr. No";
            newAdaptiveTextBlock.Weight = TextWeight;
            newAdaptiveTextBlock.Size   = TextSize;
            newAdaptiveTextBlock.Color  = TextColor;
            return(newAdaptiveTextBlock);
        }
        /// <summary>
        /// Method to send goal reminder card to team and team members or update team goal, personal goal and note details in storage.
        /// </summary>
        /// <param name="teamGoalDetail">Holds team goal detail entity data sent from background service.</param>
        /// <param name="isReminderBeforeThreeDays">Determines reminder to be sent prior 3 days to end date.</param>
        /// <returns>A Task represents goal reminder card is sent to team and team members.</returns>
        public async Task SendGoalReminderToTeamAndTeamMembersAsync(TeamGoalDetail teamGoalDetail, bool isReminderBeforeThreeDays = false)
        {
            teamGoalDetail = teamGoalDetail ?? throw new ArgumentNullException(nameof(teamGoalDetail));

            try
            {
                var    teamId     = teamGoalDetail.TeamId;
                string serviceUrl = teamGoalDetail.ServiceUrl;
                MicrosoftAppCredentials.TrustServiceUrl(serviceUrl);

                var conversationReference = new ConversationReference()
                {
                    ChannelId = Constants.TeamsBotFrameworkChannelId,
                    Bot       = new ChannelAccount()
                    {
                        Id = $"28:{this.microsoftAppCredentials.MicrosoftAppId}"
                    },
                    ServiceUrl   = serviceUrl,
                    Conversation = new ConversationAccount()
                    {
                        ConversationType = Constants.ChannelConversationType, IsGroup = true, Id = teamId, TenantId = this.options.Value.TenantId
                    },
                };

                await this.retryPolicy.ExecuteAsync(async() =>
                {
                    try
                    {
                        await((BotFrameworkAdapter)this.adapter).ContinueConversationAsync(
                            this.microsoftAppCredentials.MicrosoftAppId,
                            conversationReference,
                            async(turnContext, cancellationToken) =>
                        {
                            string reminderType = string.Empty;
                            AdaptiveTextColor reminderTypeColor = AdaptiveTextColor.Accent;
                            if (isReminderBeforeThreeDays)
                            {
                                reminderType      = this.localizer.GetString("TeamGoalEndingAfterThreeDays");
                                reminderTypeColor = AdaptiveTextColor.Warning;
                            }
                            else
                            {
                                reminderType = this.GetReminderTypeString(teamGoalDetail.ReminderFrequency);
                            }

                            var goalReminderAttachment = MessageFactory.Attachment(GoalReminderCard.GetGoalReminderCard(this.localizer, this.options.Value.ManifestId, this.options.Value.GoalsTabEntityId, reminderType, reminderTypeColor));
                            this.logger.LogInformation($"Sending goal reminder card to teamId: {teamId}");
                            await turnContext.SendActivityAsync(goalReminderAttachment, cancellationToken);
                            await this.SendGoalReminderToTeamMembersAsync(turnContext, teamGoalDetail, goalReminderAttachment, cancellationToken);
                        },
                            CancellationToken.None);
                    }
                    catch (Exception ex)
                    {
                        this.logger.LogError(ex, $"Error while performing retry logic to send goal reminder card for : {teamGoalDetail.TeamGoalId}.");
                        throw;
                    }
                });
            }
            #pragma warning disable CA1031 // Catching general exceptions to log exception details in telemetry client.
            catch (Exception ex)
            #pragma warning restore CA1031 // Catching general exceptions to log exception details in telemetry client.
            {
                this.logger.LogError(ex, $"Error while sending goal reminder in team from background service for : {teamGoalDetail.TeamGoalId} at {nameof(this.SendGoalReminderToTeamAndTeamMembersAsync)}");
            }
        }
        /// <summary>
        /// Gets the goal reminder card.
        /// </summary>
        /// <param name="localizer">The current cultures' string localizer.</param>
        /// <param name="applicationManifestId">Application manifest id.</param>
        /// <param name="goalsTabEntityId">Goals tab entity id for personal Bot.</param>
        /// <param name="reminderTypeString">Reminder type string based on reminder frequency.</param>
        /// <param name="reminderTypeStringColor">Reminder type string color based on reminder frequency.</param>
        /// <returns>Goal reminder card attachment.</returns>
        public static Attachment GetGoalReminderCard(IStringLocalizer <Strings> localizer, string applicationManifestId, string goalsTabEntityId, string reminderTypeString, AdaptiveTextColor reminderTypeStringColor)
        {
            AdaptiveCard goalReminderCard = new AdaptiveCard(Constants.AdaptiveCardVersion)
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveTextBlock
                    {
                        HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                        Wrap   = true,
                        Text   = localizer.GetString("GoalReminderCardTitle"),
                        Weight = AdaptiveTextWeight.Bolder,
                        Size   = AdaptiveTextSize.Large,
                    },
                    new AdaptiveTextBlock
                    {
                        HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                        Wrap  = true,
                        Text  = reminderTypeString,
                        Color = reminderTypeStringColor,
                    },
                    new AdaptiveTextBlock
                    {
                        HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                        Wrap = true,
                        Text = localizer.GetString("GoalReminderCardContentText"),
                    },
                },
            };

            goalReminderCard.Actions = new List <AdaptiveAction>
            {
                new AdaptiveOpenUrlAction
                {
                    Title = localizer.GetString("ViewGoalsButtonText"),
                    Url   = new Uri($"https://teams.microsoft.com/l/entity/{applicationManifestId}/{goalsTabEntityId}"), // Open Goals tab (deep link).
                },
            };

            return(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = goalReminderCard,
            });
        }