public void RenderFallbackItem() { var json = @"{ ""type"": ""AdaptiveCard"", ""version"": ""1.2"", ""body"": [ { ""type"": ""Graph"", ""text"": ""First textblock"", ""fallback"": { ""type"": ""TextBlock"", ""text"": ""Fallback textblock"" } } ] }"; var card = AdaptiveCard.FromJson(json).Card; var renderer = new AdaptiveCardRenderer(); var result = renderer.RenderCard(card); var generatedHtml = result.Html.ToString(); Assert.AreEqual("<div class='ac-adaptivecard' style='width: 100%;background-color: rgba(255, 255, 255, 1.00);padding: 15px;box-sizing: border-box;justify-content: flex-start;'><div class='ac-textblock' style='box-sizing: border-box;text-align: left;color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;white-space: nowrap;'><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;text-overflow: ellipsis;overflow: hidden;'>Fallback textblock</p></div></div>", generatedHtml); }
public async Task <ActionResult> Details(string announcementid) { AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(); if (string.IsNullOrEmpty(announcementid)) { return(HttpNotFound()); } var announcement = await Cache.Announcements.GetItemAsync(announcementid); AnnouncementDetails announcementinfo = new AnnouncementDetails(); if (announcement != null) { announcement.ShowAllDetailsButton = false; var html = announcement.GetPreviewCard(); announcement.ShowAllDetailsButton = true; RenderedAdaptiveCard renderedCard = renderer.RenderCard(html); HtmlTag cardhtml = renderedCard.Html; announcementinfo.Title = announcement.Title; announcementinfo.html = cardhtml; } return(View(announcementinfo)); }
protected override void OnElementChanged(ElementChangedEventArgs <AdaptiveCardLayout> e) { var renderer = new AdaptiveCardRenderer(); var activity = e.NewElement.BindingContext as Bot.Connector.DirectLine.Activity; var oldActivity = e.OldElement?.BindingContext as Bot.Connector.DirectLine.Activity; if (!string.Equals(oldActivity?.Id, activity?.Id)) { if (activity.Attachments != null && activity.Attachments.Any(m => m.ContentType == "application/vnd.microsoft.card.adaptive")) { var cardAttachments = activity.Attachments.Where(m => m.ContentType == "application/vnd.microsoft.card.adaptive"); foreach (var attachment in cardAttachments) { var jObject = (JObject)attachment.Content; AdaptiveCard card = null; try { card = jObject.ToObject <AdaptiveCard>(); } catch (Exception ex) { // GETTING Deserializing error here // Message "Error converting value \"number\" to type 'AdaptiveCards.TextInputStyle'. Path 'style'." string } Device.BeginInvokeOnMainThread(() => { if (!e.NewElement.Children.Any()) { var xaml = renderer.RenderCard(card); // RecurseForButtons(xaml.View); if (xaml.View != null) { xaml.OnAction += (s, args) => e.NewElement.InvokeOnAction(s, args); xaml.View.WidthRequest = 350; xaml.View.Margin = new Thickness(8); xaml.View.BackgroundColor = Color.LightGray; e.NewElement.Children.Add(xaml.View); MessagingCenter.Send(this, "ScrollToBottom"); } else { e.NewElement.Children.Add(new Label() { Text = activity.Summary }); } } }); } } base.OnElementChanged(e); } }
public void TextBlocks_Markdown() { var card = new AdaptiveCard("1.2") { Body = new System.Collections.Generic.List <AdaptiveElement>() { new AdaptiveRichTextBlock() { Inlines = { new AdaptiveTextRun { Text = "The RichTextBlock should not support **markdown**" } } }, new AdaptiveTextBlock() { Text = "The TextBlock should support **markdown**" } } }; var renderer = new AdaptiveCardRenderer(); var result = renderer.RenderCard(card); var generatedHtml = result.Html.ToString(); Assert.AreEqual( "<div class='ac-adaptivecard' style='width: 100%;background-color: rgba(255, 255, 255, 1.00);padding: 15px;box-sizing: border-box;justify-content: flex-start;'><div class='ac-richtextblock' style='box-sizing: border-box;text-align: left;word-wrap: break-word;'><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;'><span class='ac-textrun' style='color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;'>The RichTextBlock should not support **markdown**</span></p></div><div class='ac-separator' style='height: 8px;'></div><div class='ac-textblock' style='box-sizing: border-box;text-align: left;color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;white-space: nowrap;'><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;text-overflow: ellipsis;overflow: hidden;'>The TextBlock should support <strong>markdown</strong></p></div></div>", generatedHtml); }
private async void OnRenderAdaptiveCard(object sender, RoutedEventArgs e) { AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(); //string result = System.Reflection.Assembly.GetExecutingAssembly().Location; //int index = result.LastIndexOf("\\"); //string jsonPath = $"{result.Substring(0, index)}\\adaptivecard.json"; //TextReader tr = new StreamReader(jsonPath); //string json = await tr.ReadToEndAsync(); HttpClient client = new HttpClient(); json = await client.GetStringAsync("https://adaptivecard.azurewebsites.net/api/AppConsultAdaptiveCards?code=AzSEpdNE/P0c9OFIBjro2vSKwGIlLdBWdc53/jmR7Y9PX2l1Ks0/nQ=="); AdaptiveCardParseResult card = AdaptiveCard.FromJson(json); var renderResult = renderer.RenderCard(card.Card); renderResult.OnAction += RenderResult_OnAction; if (renderResult != null) { MainPanel.Children.Add(renderResult.FrameworkElement); } }
public ShowCardWindow(string title, AdaptiveShowCardAction showCardAction) { InitializeComponent(); var renderer = new AdaptiveCardRenderer(); var renderedCard = renderer.RenderCard(showCardAction.Card); this.rootGrid.Children.Clear(); this.rootGrid.Children.Add(renderedCard.FrameworkElement); }
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is AdaptiveCard ac) { var result = renderer.RenderCard(ac); return(result.FrameworkElement); } return(null); }
private void Update() { try { var renderer = new AdaptiveCardRenderer(AdaptiveHostConfig.FromJson(HostConfigs.CortanaHostConfig)); CardContainer.Child = renderer.RenderCard(AdaptiveCard.FromJson(TextBoxCard.Text).Card).FrameworkElement; } catch { } }
protected override void OnElementChanged(ElementChangedEventArgs <AdaptiveCardLayout> e) { if (e.NewElement != null) { var activity = e.NewElement.BindingContext as Bot.Connector.DirectLine.Activity; if (activity?.Attachments != null && activity.Attachments.Any(m => m.ContentType == "application/vnd.microsoft.card.adaptive")) { var cardAttachments = activity.Attachments.Where(m => m.ContentType == "application/vnd.microsoft.card.adaptive"); foreach (var attachment in cardAttachments) { var jObject = (JObject)attachment.Content; AdaptiveCards.AdaptiveCard card; try { card = jObject.ToObject <AdaptiveCard>(); } catch (Exception ex) { return; } Device.BeginInvokeOnMainThread(() => { if (!e.NewElement.Children.Any()) { var xaml = _adaptiveCardsRenderer.RenderCard(card); if (xaml.View != null) { xaml.OnAction += (s, args) => e.NewElement.InvokeOnAction(s, args); xaml.View.WidthRequest = 350; xaml.View.Margin = new Thickness(8); xaml.View.BackgroundColor = Color.LightGray; e.NewElement.Children.Add(xaml.View); MessagingCenter.Send(this, "ReloadUITableViewData"); } else { e.NewElement.Children.Add(new Label() { Text = activity.Summary }); } } }); } } } base.OnElementChanged(e); }
public void ContainerStyleForegroundColors() { var hostConfig = new AdaptiveHostConfig(); hostConfig.ContainerStyles.Emphasis.ForegroundColors = new ForegroundColorsConfig() { Default = new FontColorConfig("#FFcc3300") }; var card = new AdaptiveCard("1.2") { Body = new System.Collections.Generic.List <AdaptiveElement>() { new AdaptiveContainer() { Style = AdaptiveContainerStyle.Emphasis, Items = new System.Collections.Generic.List <AdaptiveElement>() { new AdaptiveTextBlock() { Text = "container 1 -- emphasis style text" }, new AdaptiveContainer() { Style = AdaptiveContainerStyle.Accent, Items = new System.Collections.Generic.List <AdaptiveElement>() { new AdaptiveTextBlock() { Text = "container 1.1 -- accent style text" } } }, new AdaptiveTextBlock() { Text = "container 1 -- emphasis style text" } } }, new AdaptiveTextBlock() { Text = "default style text" } } }; var renderer = new AdaptiveCardRenderer(hostConfig); var result = renderer.RenderCard(card); var generatedHtml = result.Html.ToString(); var randomGeneratedIds = FindAllRandomGeneratedIds(generatedHtml); Assert.AreEqual( "<div class='ac-adaptivecard' style='width: 100%;background-color: rgba(255, 255, 255, 1.00);padding: 15px;box-sizing: border-box;justify-content: flex-start;'><div class='ac-container' style='padding-right: 15px;padding-left: 15px;padding-top: 15px;padding-bottom: 15px;background-color: rgba(0, 0, 0, 0.03);justify-content: flex-start;'><div class='ac-textblock' style='box-sizing: border-box;text-align: left;color: rgba(204, 51, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;white-space: nowrap;'><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;text-overflow: ellipsis;overflow: hidden;'>container 1 -- emphasis style text</p></div><div class='ac-separator' id='" + randomGeneratedIds[0] + "' style='height: 8px;'></div><div class='ac-container' data-ac-separatorId='" + randomGeneratedIds[0] + "' style='padding-right: 15px;padding-left: 15px;padding-top: 15px;padding-bottom: 15px;background-color: #dce5f7;justify-content: flex-start;'><div class='ac-textblock' style='box-sizing: border-box;text-align: left;color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;white-space: nowrap;'><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;text-overflow: ellipsis;overflow: hidden;'>container 1.1 -- accent style text</p></div></div><div class='ac-separator' id='" + randomGeneratedIds[1] + "' style='height: 8px;'></div><div class='ac-textblock' data-ac-separatorId='" + randomGeneratedIds[1] + "' style='box-sizing: border-box;text-align: left;color: rgba(204, 51, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;white-space: nowrap;'><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;text-overflow: ellipsis;overflow: hidden;'>container 1 -- emphasis style text</p></div></div><div class='ac-separator' id='" + randomGeneratedIds[2] + "' style='height: 8px;'></div><div class='ac-textblock' data-ac-separatorId='" + randomGeneratedIds[2] + "' style='box-sizing: border-box;text-align: left;color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;white-space: nowrap;'><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;text-overflow: ellipsis;overflow: hidden;'>default style text</p></div></div>", generatedHtml); }
/// <summary> /// Create WeChat news instance from the given adaptive card. /// </summary> /// <param name="activity">Message activity received from bot.</param> /// <param name="adaptiveCard">Adaptive card instance.</param> /// <param name="title">Title or name of the card attachment.</param> /// <returns>A <seealso cref="News"/> converted from adaptive card.</returns> private async Task <News> CreateNewsFromAdaptiveCard(IMessageActivity activity, AdaptiveCard adaptiveCard, string title) { try { if (!adaptiveCard.AdditionalProperties.ContainsKey(CoverImageUrlKey)) { throw new ArgumentException("Cover image is required.", nameof(adaptiveCard)); } if (!adaptiveCard.AdditionalProperties.ContainsKey(ContentSourceUrlKey)) { throw new ArgumentException("Content source URL is required.", nameof(adaptiveCard)); } var renderer = new AdaptiveCardRenderer(); var schemaVersion = renderer.SupportedSchemaVersion; var converImageUrl = adaptiveCard.AdditionalProperties[CoverImageUrlKey].ToString(); var attachmentData = await CreateAttachmentDataAsync(title ?? activity.Text, converImageUrl, MediaTypes.Image).ConfigureAwait(false); var thumbMediaId = (await _wechatClient.UploadMediaAsync(attachmentData, false).ConfigureAwait(false)).MediaId; // Replace all image URL to WeChat acceptable URL foreach (var element in adaptiveCard.Body) { await ReplaceAdaptiveImageUri(element).ConfigureAwait(false); } // Render the card var renderedCard = renderer.RenderCard(adaptiveCard); var html = renderedCard.Html; // (Optional) Check for any renderer warnings // This includes things like an unknown element type found in the card // Or the card exceeded the maximum number of supported actions, etc var warnings = renderedCard.Warnings; var news = new News { Author = activity.From.Name, Description = adaptiveCard.Speak ?? adaptiveCard.FallbackText, Content = html.ToString(), Title = title, // Set not should cover, because adaptive card don't have a cover. ShowCoverPicture = "0", ContentSourceUrl = adaptiveCard.AdditionalProperties[ContentSourceUrlKey].ToString(), ThumbMediaId = thumbMediaId, }; return(news); } catch (Exception ex) { _logger.LogError(ex, "Process adaptive card failed."); throw; } }
private void OnShowCard(object sender, RoutedEventArgs e) { void ShowSubmitAction(RenderedAdaptiveCard card, AdaptiveSubmitAction action) { var inputs = card.UserInputs.AsJson(); inputs.Merge(action.Data); MessageBox.Show(JsonConvert.SerializeObject(inputs, Formatting.Indented)); } void ShowCardAction(RenderedAdaptiveCard card, AdaptiveShowCardAction action) { if (_hostConfig.Actions.ShowCard.ActionMode == ShowCardActionMode.Popup) { var dialog = new ShowCardWindow("Show Card", action); dialog.Owner = this; dialog.ShowDialog(); } } void OpenUrlAction(RenderedAdaptiveCard card, AdaptiveOpenUrlAction action) { webBrowser.Navigate(action.Url.ToString()); } AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(_hostConfig); var version = renderer.SupportedSchemaVersion; // renderer.UseXceedElementRenderers(); var result = AdaptiveCard.FromJson(LoadJson()); var renderedCard = renderer.RenderCard(result.Card); renderedCard.OnAction += (RenderedAdaptiveCard card, AdaptiveActionEventArgs args) => { switch (args.Action) { case AdaptiveSubmitAction submitAction: ShowSubmitAction(card, submitAction); break; case AdaptiveShowCardAction showCardAction: ShowCardAction(card, showCardAction); break; case AdaptiveOpenUrlAction openUrlAction: OpenUrlAction(card, openUrlAction); break; default: break; } }; grid1.Children.Clear(); grid1.Children.Add(renderedCard.FrameworkElement); }
private void RenderCard() { cardError.Children.Clear(); cardGrid.Children.Clear(); try { AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(textBox.Text, textBoxData.Text); AdaptiveCard card = parseResult.Card; /* * // Example on how to override the Action Positive and Destructive styles * Style positiveStyle = new Style(typeof(Button)); * positiveStyle.Setters.Add(new Setter(Button.BackgroundProperty, Brushes.Green)); * Style otherStyle = new Style(typeof(Button)); * otherStyle.Setters.Add(new Setter(Button.BackgroundProperty, Brushes.Yellow)); * otherStyle.Setters.Add(new Setter(Button.ForegroundProperty, Brushes.Red)); * * Renderer.Resources.Add("Adaptive.Action.Submit.positive", positiveStyle); * Renderer.Resources.Add("Adaptive.Action.Submit.other", otherStyle); */ RenderedAdaptiveCard renderedCard = Renderer.RenderCard(card); // TODO: should we have an option to render fallback card instead of exception? // Wire up click handler renderedCard.OnAction += OnAction; renderedCard.OnMediaClicked += OnMediaClick; cardGrid.Children.Add(renderedCard.FrameworkElement); // Report any warnings var allWarnings = parseResult.Warnings.Union(renderedCard.Warnings); foreach (var warning in allWarnings) { ShowWarning(warning.Message); } } catch (AdaptiveRenderException ex) { var fallbackCard = new TextBlock { Text = ex.CardFallbackText ?? "Sorry, we couldn't render the card" }; cardGrid.Children.Add(fallbackCard); } catch (Exception ex) { ShowError(ex); } }
public static async Task Main(string[] args) { configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName) .AddJsonFile("appsettings.json", false) .AddJsonFile("appsettings.local.json", true) .Build(); var templateJson = File.ReadAllText("Template1.json", Encoding.UTF8); var data = new { tenantname = "Stavanger", categoryname = "Avløp", statusname = "Under prosessering", deadline = "2020-02-07T09:20:00Z", taskurl = "https://melding.powel.net/stavanger/tasks/some-random-id" }; var dataJson = JsonConvert.SerializeObject(data); var transformer = new AdaptiveCards.Templating.AdaptiveTransformer(); var transformed = transformer.Transform(templateJson, dataJson); var hostConfig = new AdaptiveHostConfig { SupportsInteractivity = true }; var renderer = new AdaptiveCardRenderer(hostConfig); // make link html simpler - Outlook is not good at rendering html! renderer.ElementRenderers.Remove <AdaptiveOpenUrlAction>(); renderer.ElementRenderers.Set <AdaptiveOpenUrlAction>((action, context) => { var aTag = new HtmlTag("a").AddClass("ac-action-openUrl"); aTag.Attributes.Add("href", action.Url.ToString()); aTag.Text = action.Title; return(aTag); }); var parsedCard = AdaptiveCard.FromJson(transformed); parsedCard.Card.Lang = "nb-no"; // set to whatever language makes more sense var renderedCard = renderer.RenderCard(parsedCard.Card); var htmlContent = renderedCard.Html.ToString(); var from = new EmailAddress("*****@*****.**", "Ikke svar"); var subject = "Ny oppgave fra Powel Melding"; var to = new EmailAddress("*****@*****.**", "Jarle Nygård"); var msg = MailHelper.CreateSingleEmail(from, to, subject, string.Empty, htmlContent); var client = new SendGridClient(configuration["SendgridApiKey"]); var response = await client.SendEmailAsync(msg); }
public async Task OnGet() { HttpClient client = new HttpClient(); string json = await client.GetStringAsync("https://adaptivecard.azurewebsites.net/api/AppConsultAdaptiveCards?code=AzSEpdNE/P0c9OFIBjro2vSKwGIlLdBWdc53/jmR7Y9PX2l1Ks0/nQ=="); AdaptiveCardParseResult card = AdaptiveCards.AdaptiveCard.FromJson(json); AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(); RenderedAdaptiveCard renderedCard = renderer.RenderCard(card.Card); // Get the output HTML AdaptiveCard = new HtmlString(renderedCard.Html.ToString()); }
public void RichTextBlockRender_MultipleParagraphs() { var card = new AdaptiveCard("1.2") { Body = new System.Collections.Generic.List <AdaptiveElement>() { new AdaptiveRichTextBlock() { Paragraphs = { new AdaptiveRichTextBlock.AdaptiveParagraph() { Inlines = { new AdaptiveRichTextBlock.AdaptiveParagraph.AdaptiveTextRun { Text = "Paragraph 1 Inline 1" }, new AdaptiveRichTextBlock.AdaptiveParagraph.AdaptiveTextRun { Text = "Paragraph 1 Inline 2" } } }, new AdaptiveRichTextBlock.AdaptiveParagraph() { Inlines = { new AdaptiveRichTextBlock.AdaptiveParagraph.AdaptiveTextRun { Text = "Paragraph 2 Inline 1" }, new AdaptiveRichTextBlock.AdaptiveParagraph.AdaptiveTextRun { Text = "Paragraph 2 Inline 2" } } } } } } }; var renderer = new AdaptiveCardRenderer(); var result = renderer.RenderCard(card); var generatedHtml = result.Html.ToString(); Assert.AreEqual( "<div class='ac-adaptivecard' style='width: 100%;background-color: rgba(255, 255, 255, 1.00);padding: 15px;box-sizing: border-box;justify-content: flex-start;'><div class='ac-richtextblock' style='box-sizing: border-box;text-align: left;white-space: nowrap;'><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;text-overflow: ellipsis;overflow: hidden;'><span class='ac-textrun' style='color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;'>Paragraph 1 Inline 1</span><span class='ac-textrun' style='color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;'>Paragraph 1 Inline 2</span></p><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;text-overflow: ellipsis;overflow: hidden;'><span class='ac-textrun' style='color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;'>Paragraph 2 Inline 1</span><span class='ac-textrun' style='color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;'>Paragraph 2 Inline 2</span></p></div></div>", generatedHtml); }
private static string RenderAdaptiveCardHtml(string adaptiveCardJson) { var generatedCard = JsonConvert.DeserializeObject <AdaptiveCard>(adaptiveCardJson); var renderer = new AdaptiveCardRenderer(); var renderedCard = renderer.RenderCard(generatedCard); foreach (var w in renderedCard.Warnings) { Console.Error.WriteLine($"[warning] {w.Code}: {w.Message}"); } return(renderedCard.Html.ToString()); }
private void Window_Loaded(object sender, RoutedEventArgs e) { var renderer = new AdaptiveCardRenderer(new AdaptiveHostConfig()) { Resources = _resources }; var result = renderer.RenderCard(_card.Card); if (result.FrameworkElement != null) { // Wire up click handler result.OnAction += OnAction; Body.Children.Add(result.FrameworkElement); } }
public async Task <ActionResult> Duty(string code, string userEmailId) { Portal portal = new Portal(); AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(); var card = await CardHelper.GetMyDetailedCard(code, userEmailId); if (card == null) { return(HttpNotFound()); } RenderedAdaptiveCard renderedCard = renderer.RenderCard(card.Content as AdaptiveCard); HtmlTag cardhtml = renderedCard.Html; portal.html = cardhtml; return(View("AdaptiveCardRenderer", portal)); }
public async Task <ActionResult> Duty(string code, string userEmailId) { Portal portal = new Portal(); AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(); // var card = await CardHelper.GetMyDetailedCard(code, "10055"); // ${Debugging} var card = await CardHelper.GetMyDetailedCard(code, userEmailId, configuration); if (card == null) { return(StatusCode(404)); } RenderedAdaptiveCard renderedCard = renderer.RenderCard(card.Content as AdaptiveCard); HtmlTag cardhtml = renderedCard.Html; portal.html = cardhtml; return(View("AdaptiveCardRenderer", portal)); }
public async Task <IList <Activity> > GetMessages() { var response = await _client.Conversations .GetActivitiesAsync(_conversation.ConversationId, _watermark) .ConfigureAwait(false); var cardAttachments = response.Activities .Where(m => m.Attachments != null) .SelectMany(m => m.Attachments) .Where(m => m.ContentType == "application/vnd.microsoft.card.adaptive"); foreach (var attachment in cardAttachments) { var jObject = (JObject)attachment.Content; var card = jObject.ToObject <AdaptiveCard>(); Device.BeginInvokeOnMainThread(() => { var result = _renderer.RenderCard(card); if (result.View != null) { // Wire up click handler result.OnAction += (s, args) => { _onAction?.Invoke(s, args); }; var xaml = result.View; xaml.WidthRequest = 350; xaml.Margin = new Thickness(8); xaml.BackgroundColor = Color.LightGray; Items.Children.Add(xaml); } }); } _watermark = response.Watermark; return(response.Activities); }
public void RichTextBlockRender_MultipleInlines() { var card = new AdaptiveCard("1.2") { Body = new System.Collections.Generic.List <AdaptiveElement>() { new AdaptiveRichTextBlock() { Inlines = { new AdaptiveTextRun { Text = "Inline 1" }, new AdaptiveTextRun { Text = "Inline 2" }, new AdaptiveTextRun { Text = "Inline 3" }, new AdaptiveTextRun { Text = "Inline 4", Italic = true, Strikethrough = true, Highlight = true } } } } }; var renderer = new AdaptiveCardRenderer(); var result = renderer.RenderCard(card); var generatedHtml = result.Html.ToString(); Assert.AreEqual( "<div class='ac-adaptivecard' style='width: 100%;background-color: rgba(255, 255, 255, 1.00);padding: 15px;box-sizing: border-box;justify-content: flex-start;'><div class='ac-richtextblock' style='box-sizing: border-box;text-align: left;word-wrap: break-word;'><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;'><span class='ac-textrun' style='color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;'>Inline 1</span><span class='ac-textrun' style='color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;'>Inline 2</span><span class='ac-textrun' style='color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;'>Inline 3</span><span class='ac-textrun' style='color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;font-style: italic;text-decoration: line-through;background-color: rgba(255, 255, 0, 1.00);'>Inline 4</span></p></div></div>", generatedHtml); }
private void RenderCard() { cardError.Children.Clear(); cardGrid.Children.Clear(); try { AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(textBox.Text); AdaptiveCard card = parseResult.Card; RenderedAdaptiveCard renderedCard = Renderer.RenderCard(card); // TODO: should we have an option to render fallback card instead of exception? // Wire up click handler renderedCard.OnAction += OnAction; renderedCard.OnMediaClicked += OnMediaClick; cardGrid.Children.Add(renderedCard.FrameworkElement); // Report any warnings var allWarnings = parseResult.Warnings.Union(renderedCard.Warnings); foreach (var warning in allWarnings) { ShowWarning(warning.Message); } } catch (AdaptiveRenderException ex) { var fallbackCard = new TextBlock { Text = ex.CardFallbackText ?? "Sorry, we couldn't render the card" }; cardGrid.Children.Add(fallbackCard); } catch (Exception ex) { ShowError(ex); } }
private void OnShowCard(object sender, RoutedEventArgs e) { var renderer = new AdaptiveCardRenderer(_hostconfig); var version = renderer.SupportedSchemaVersion; // renderer.UseXceedElementRenderers(); var json = LoadJson(); grid1.Children.Clear(); if (json is "") { return; } var result = AdaptiveCard.FromJson(json); var renderedCard = renderer.RenderCard(result.Card); renderedCard.OnAction += (card, args) => { switch (args.Action) { case AdaptiveOpenUrlAction openUrlAction: Process.Start(openUrlAction.Url.ToString()); break; case AdaptiveShowCardAction showCardAction: // Eine weitere Adaptive Card anzeigen // Inline oder als Popup break; case AdaptiveSubmitAction submitAction: var inputs = card.UserInputs.AsJson(); inputs.Merge(submitAction.Data); MessageBox.Show(this, JsonConvert.SerializeObject(inputs, Formatting.Indented), "SubmitAction"); break; } }; grid1.Children.Add(renderedCard.FrameworkElement); }
public void TextBlockRender_ItalicAndStrikethrough() { AdaptiveCard card = new AdaptiveCard("1.2") { Body = new System.Collections.Generic.List <AdaptiveElement>() { new AdaptiveTextBlock("Some italic struck-through text") { Italic = true, Strikethrough = true } } }; var renderer = new AdaptiveCardRenderer(); var result = renderer.RenderCard(card); var generatedHtml = result.Html.ToString(); Assert.AreEqual("<div class='ac-adaptivecard' style='width: 100%;background-color: rgba(255, 255, 255, 1.00);padding: 15px;box-sizing: border-box;justify-content: flex-start;'><div class='ac-textblock' style='box-sizing: border-box;text-align: left;color: rgba(0, 0, 0, 1.00);line-height: 18.62px;font-size: 14px;font-weight: 400;font-style: italic;text-decoration: line-through;white-space: nowrap;'><p style='margin-top: 0px;margin-bottom: 0px;width: 100%;text-overflow: ellipsis;overflow: hidden;'>Some italic struck-through text</p></div></div>", generatedHtml); }
private void UpdateAdaptiveCard(ItemViewModel item) { _cardTitleTextBlock.Text = $"{item.Name}, expected to start at " + $"{item.DevelopmentStartDate.ToShortDateString()} and completed at " + $"{item.ExpectedCompletionDate.ToShortDateString()}."; if (_renderedCard != null) { adaptiveCardContainer.Children.Clear(); _renderedCard.OnAction -= RenderedCard_OnAction; _renderedCard = null; } try { _renderedCard = _renderer.RenderCard(_card); _renderedCard.OnAction += RenderedCard_OnAction; adaptiveCardContainer.Children.Add(_renderedCard.FrameworkElement); } catch (AdaptiveException exception) { Debug.WriteLine(exception); } }
static int Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; var app = new CommandLineApplication(); app.HelpOption("-h|--help"); var pathArg = app.Argument("path", "The path that contains JSON card payloads"); var optionRecurse = app.Option("-r|--recursive", "Recurse the directory for all JSON files", CommandOptionType.NoValue); var optionOutput = app.Option("-o|--out", "The file to output the HTML to", CommandOptionType.SingleValue); var optionSupportsInteracitivty = app.Option("-i|--supports-interactivity", "Include actions and inputs in the output", CommandOptionType.NoValue); var hostConfigOption = app.Option("--host-config", "Specify a host config file", CommandOptionType.SingleValue); app.OnExecute(() => { FileStream outputFile = null; var writer = Console.Out; // Output to file instead of console if (optionOutput.HasValue()) { outputFile = File.Open(optionOutput.Value(), FileMode.Create); writer = new StreamWriter(outputFile); } // Get payload search path var payloadPath = pathArg.Value ?? "..\\..\\..\\..\\samples\\v1.0\\Scenarios"; if (pathArg.Value == null) { Console.WriteLine($"No path argument specified, trying {payloadPath}..."); } var files = new List <string>(); if (File.Exists(payloadPath)) { files.Add(payloadPath); } else if (Directory.Exists(payloadPath)) { var recurse = optionRecurse.HasValue() ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; files = Directory.GetFiles(payloadPath, "*.json", recurse).ToList(); Console.WriteLine($"Found {files.Count} card payloads..."); } else { Console.WriteLine($"{payloadPath} does not contain any JSON files/. Nothing to do."); return; } writer.WriteLine(@"<!DOCTYPE html>"); writer.WriteLine(@"<html>"); writer.WriteLine(@"<head>"); writer.WriteLine(@" <title>Adaptive Cards HTML Renderer Test Bed</title>"); writer.WriteLine(@" <meta charset=""UTF-8"">"); writer.WriteLine(@" <link rel='stylesheet' type='text/css' href='AdaptiveCards.css' />"); writer.WriteLine(@"</head>"); writer.WriteLine(@"<body>"); AdaptiveHostConfig hostConfig = new AdaptiveHostConfig() { SupportsInteractivity = optionSupportsInteracitivty.HasValue() }; if (hostConfigOption.HasValue()) { hostConfig = AdaptiveHostConfig.FromJson(File.ReadAllText(hostConfigOption.Value())); } AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(hostConfig); writer.WriteLine($"<h3>Renderer schema version: {renderer.SupportedSchemaVersion}</h3>"); writer.WriteLine($"<h4>Interactivty Enabled: {hostConfig.SupportsInteractivity}</h4>"); writer.WriteLine($"<h4>Generated at: {DateTime.Now:G}</h4>"); foreach (var file in files) { try { writer.WriteLine("<hr/>"); writer.WriteLine($"<h2>{Path.GetFileName(file)}</h2>"); AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(File.ReadAllText(file, Encoding.UTF8)); AdaptiveCard card = parseResult.Card; RenderedAdaptiveCard renderedCard = renderer.RenderCard(card); // Report any warnings foreach (var warning in parseResult.Warnings.Union(renderedCard.Warnings)) { writer.WriteLine($"<p class='warning'>WARNING: {warning.Message}</p>"); } writer.WriteLine($"<div class='cardcontainer'>{renderedCard.Html}</div>"); } catch (Exception err) { Debugger.Break(); writer.WriteLine($"<p class='error'>ERROR: {err.Message}</p>"); } } writer.WriteLine("</body>"); writer.WriteLine("</html>"); if (outputFile != null) { writer.Flush(); outputFile.Flush(); outputFile.Dispose(); Console.WriteLine($"All cards were written to {outputFile.Name}"); } // if output, launch the file if (Debugger.IsAttached) { Console.ReadLine(); } }); return(app.Execute(args)); }
static int Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; var app = new CommandLineApplication(); app.HelpOption("-h|--help"); var pathArg = app.Argument("path", "The path that contains JSON card payloads"); var optionRecurse = app.Option("-r|--recursive", "Recurse the directory for all JSON files", CommandOptionType.NoValue); var optionOutput = app.Option("-o|--out", "The file to output the HTML to", CommandOptionType.SingleValue); var optionSupportsInteracitivty = app.Option("-i|--supports-interactivity", "Include actions and inputs in the output", CommandOptionType.NoValue); var hostConfigOption = app.Option("--host-config", "Specify a host config file", CommandOptionType.SingleValue); app.OnExecute(() => { FileStream outputFile = null; var writer = Console.Out; // Output to file instead of console if (optionOutput.HasValue()) { outputFile = File.Open(optionOutput.Value(), FileMode.Create); writer = new StreamWriter(outputFile); } // Get payload search path var payloadPath = pathArg.Value ?? "..\\..\\..\\..\\samples\\v1.0\\Scenarios"; if (pathArg.Value == null) { Console.WriteLine($"No path argument specified, trying {payloadPath}..."); } var files = new List <string>(); if (File.Exists(payloadPath)) { files.Add(payloadPath); } else if (Directory.Exists(payloadPath)) { var recurse = optionRecurse.HasValue() ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; files = Directory.GetFiles(payloadPath, "*.json", recurse).ToList(); Console.WriteLine($"Found {files.Count} card payloads..."); } else { Console.WriteLine($"{payloadPath} does not contain any JSON files. Nothing to do."); return; } writer.WriteLine(@"<!DOCTYPE html> <html> <head> <title>Adaptive Cards HTML Renderer Test Bed</title> <meta charset=""UTF-8""> <style type""text/css""> * { box-sizing: border-box; font-family: 'Segoe UI' } .cardcontainer { width: 400px; border-width: 1px; border-color: #808080; border-style: solid; } .error { border: solid 1px maroon; color: white; background: maroon; padding: 5px; width: 400px; } .warning { border: solid 1px orange; color: white; background: orange; padding: 5px; width: 400px; } </style> </head> <body>"); AdaptiveHostConfig hostConfig = new AdaptiveHostConfig() { SupportsInteractivity = optionSupportsInteracitivty.HasValue() }; if (hostConfigOption.HasValue()) { hostConfig = AdaptiveHostConfig.FromJson(File.ReadAllText(hostConfigOption.Value())); } AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(hostConfig); writer.WriteLine($"<h3>Renderer schema version: {renderer.SupportedSchemaVersion}</h3>"); writer.WriteLine($"<h4>Interactivty Enabled: {hostConfig.SupportsInteractivity}</h4>"); writer.WriteLine($"<h4>Generated at: {DateTime.Now:G}</h4>"); foreach (var file in files) { try { writer.WriteLine("<hr/>"); writer.WriteLine($"<h2>{Path.GetFileName(file)}</h2>"); AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(File.ReadAllText(file, Encoding.UTF8)); AdaptiveCard card = parseResult.Card; RenderedAdaptiveCard renderedCard = renderer.RenderCard(card); // Report any warnings foreach (var warning in parseResult.Warnings.Union(renderedCard.Warnings)) { writer.WriteLine($"<p class='warning'>WARNING: {warning.Message}</p>"); } writer.WriteLine($"<div class='cardcontainer'>{renderedCard.Html}</div>"); } catch (Exception err) { Debugger.Break(); writer.WriteLine($"<p class='error'>ERROR: {err.Message}</p>"); } } bool allowInlinePlayback = hostConfig.Media.AllowInlinePlayback; // Convert to JavaScript boolean values (False -> false, True -> true) string jsAllowInlinePlayback = allowInlinePlayback.ToString().ToLower(); writer.WriteLine("</body>"); writer.WriteLine($@" <script> // Sample JavaScript code to make media elements work const mediaPosterButtons = document.getElementsByClassName('ac-media-poster'); const allowInlinePlayback = false; function activateMedia(button) {{ const mediaId = button.dataset.acMediaid; const mediaPlayerContainer = document.getElementById(mediaId); if (mediaPlayerContainer) {{ // Hide the poster button.style.display = 'none'; // Show the media player container mediaPlayerContainer.style.display = ''; // Play the media const mediaPlayer = document.getElementById(`${{mediaId}}-player`); mediaPlayer.play(); }} }} for (var i = 0; i < mediaPosterButtons.length; i++) {{ const button = mediaPosterButtons[i]; button.addEventListener('click', function() {{ if ({jsAllowInlinePlayback}) {{ activateMedia(button); }} else {{ const mediaSources = button.dataset.acMediaSources; alert(mediaSources); }} }}); button.addEventListener('keydown', function(e) {{ if (e.key == "" "") {{ if ({jsAllowInlinePlayback}) {{ activateMedia(button); }} else {{ const mediaSources = button.dataset.acMediaSources; alert(mediaSources); }} }} }}); }} // Sample JavaScript code to test showCard action const showCardActions = document.getElementsByClassName('ac-action-showCard'); for (var i = 0; i < showCardActions.length; i++) {{ const showCardAction = showCardActions[i]; showCardAction.addEventListener('click', function() {{ if (true) {{ const showCardId = showCardAction.dataset.acShowcardid; const showCard = document.getElementById(showCardId); if(showCard.style.display == 'none') {{ showCard.style.display = 'inline'; }} else {{ showCard.style.display = 'none' }} }} else {{ const showCardId = showCardAction.dataset.acShowCardId; alert(showCardId); }} }}); }} // Sample JavaScript code to test inlienaction's keyboard event handler const textinputWithInlineAction = document.getElementsByClassName('ac-textinput-inlineaction'); for (var i = 0; i < textinputWithInlineAction.length; i++) {{ const container = textinputWithInlineAction[i]; const textinputId = container.dataset.acTextinputId; const textinput = document.getElementById(textinputId); textinput.addEventListener('keydown', function (e) {{ if (e.key == ""Enter"") {{ const inlineactionId = container.dataset.acInlineactionId; const inlineaction = document.getElementById(inlineactionId); if (inlineaction) {{ var actionAttribute = inlineaction.getAttribute('data-ac-url'); if (actionAttribute != null) {{ window.open(actionAttribute); }} else {{ actionAttribute = inlineaction.getAttribute('data-ac-submitData') if (actionAttribute != null) {{ alert(textinput.value); }} }} }} }} }}); }} // Sample JavaScript code to test toggleVisibility action const toggleVisibilityActions = document.getElementsByClassName('ac-action-toggleVisibility'); for (var i = 0; i < toggleVisibilityActions.length; i++) {{ const toggleVisibilityAction = toggleVisibilityActions[i]; toggleVisibilityAction.addEventListener('click', function() {{ if ({jsAllowInlinePlayback}) {{ // Read list of targets with defined behaviour // List will be in format id-targets='id1:True,id2:Toggle,id3:False' const targetElementsString = toggleVisibilityAction.dataset.acTargetelements; var targetElements = targetElementsString.split(','); // For each target in list of targets for(var j = 0; j < targetElements.length; j++) {{ /// Do a split for commas and for each element, find the : to divide both strings const targetElementIdWithAction = targetElements[j].split(':'); const targetElementId = targetElementIdWithAction[0]; const targetElementAction = targetElementIdWithAction[1]; var targetElementsInDocument = document.getElementsByName(targetElementId); // There is no singular version of getElementByName so just take the first element var targetElement = targetElementsInDocument[0]; // The way to discern between checkbox elements and inline-actions is that inline-actions contain a textinput var isCheckBoxElement = ((targetElementsInDocument.length > 1) && !(targetElement.className.includes('ac-textinput'))); const targetSeparatorId = targetElement.dataset.acSeparatorid; const separator = document.getElementById(targetSeparatorId); if(targetElementAction == 'True' || (targetElementAction == 'Toggle' && targetElement.style.display == 'none')) {{ if( isCheckBoxElement ) {{ targetElement.style.display = 'inline-block'; }} else {{ targetElement.style.display = 'flex'; }} if(targetElement.className.includes('ac-container')){{ targetElement.style.display = 'block'; }} if(separator != null) {{ separator.style.display = 'block'; }} }} else if(targetElementAction == 'False' || (targetElementAction == 'Toggle' && targetElement.style.display != 'none')) {{ targetElement.style.display = 'none'; if(separator != null) {{ separator.style.display = 'none'; }} }} const parent = targetElement.parentNode; var isFirstElement = true; for(var k = 0; k < parent.childNodes.length; k++){{ var child = parent.childNodes[k]; <!-- if element is separator -> skip (As we don't care of this one) --> if(child.className.includes('ac-separator') || child.className.includes('ac-columnseparator')){{ continue; }} <!-- if element is not visible -> skip (The separator was hidden in the previous step) --> if(child.style.display == 'none'){{ continue; }} const childSeparatorId = child.dataset.acSeparatorid; var childSeparator = document.getElementById(childSeparatorId); if(isFirstElement){{ <!-- if element is visible -> hide separator --> if(childSeparator != null){{ childSeparator.style.display = 'none'; }} isFirstElement = false; }} else{{ <!-- if element is visible -> show separator --> if(childSeparator != null){{ childSeparator.style.display = 'block'; }} }} }} }} }} else {{ const targetElementsString = toggleVisibilityAction.dataset.acTargetelements; alert(targetElementsString); }} }}); }} </script>"); writer.WriteLine("</html>"); if (outputFile != null) { writer.Flush(); outputFile.Flush(); outputFile.Dispose(); Console.WriteLine($"All cards were written to {outputFile.Name}"); } // if output, launch the file if (Debugger.IsAttached) { Console.ReadLine(); } }); return(app.Execute(args)); }
public async Task <IActionResult> Register([FromBody] RegistrationBindingModel registrationBindingModel) { HtmlTag htmlTag = new HtmlTag("", true); if (string.IsNullOrWhiteSpace(registrationBindingModel.EmailAddress)) { return(BadRequest(new GenericViewModel { Message = "Email Address needs to supplied." })); } if (string.IsNullOrWhiteSpace(registrationBindingModel.PhoneNumber)) { return(BadRequest(new GenericViewModel { Message = "Phone Number needs to supplied." })); } var attendee = await _context.Attendees.FirstOrDefaultAsync(x => x.EmailAddress == registrationBindingModel.EmailAddress); if (attendee != null) { var response = StatusCode((int)HttpStatusCode.Conflict, new GenericViewModel { Message = "Sorry, a user with that email address has been registered." }); return(response); } attendee = new Models.Data.Attendee { FirstName = registrationBindingModel.FirstName, LastName = registrationBindingModel.LastName, EmailAddress = registrationBindingModel.EmailAddress, RegistrationDate = DateTime.Now }; // Create a card renderer AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(); // For fun, check the schema version this renderer supports AdaptiveSchemaVersion schemaVersion = renderer.SupportedSchemaVersion; // 1.0 // Build a simple card // In the real world this would probably be provided as JSON AdaptiveCard card = new AdaptiveCard() { Body = new List <AdaptiveElement>() { new AdaptiveContainer() { }, new AdaptiveContainer() { } }, Actions = new List <AdaptiveAction>() { new AdaptiveOpenUrlAction() { }, new AdaptiveOpenUrlAction() { } } }; try { // Render the card RenderedAdaptiveCard renderedCard = renderer.RenderCard(card); // Get the output HTML htmlTag = renderedCard.Html; // (Optional) Check for any renderer warnings // This includes things like an unknown element type found in the card // Or the card exceeded the maxmimum number of supported actions, etc IList <AdaptiveWarning> warnings = renderedCard.Warnings; } catch (AdaptiveException ex) { // Failed rendering } var _Attendee = _context.Attendees.Add(attendee); await _context.SaveChangesAsync(); await Services.EmailService.SendRegistrationEmail(attendee, htmlTag); return(Created($"http://events.windforcecorp.com/{_Attendee.Entity.AttendeeID.ToString()}", _Attendee)); }
static int Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; var app = new CommandLineApplication(); app.HelpOption("-h|--help"); var pathArg = app.Argument("path", "The path that contains JSON card payloads"); var optionRecurse = app.Option("-r|--recursive", "Recurse the directory for all JSON files", CommandOptionType.NoValue); var optionOutput = app.Option("-o|--out", "The file to output the HTML to", CommandOptionType.SingleValue); var optionSupportsInteracitivty = app.Option("-i|--supports-interactivity", "Include actions and inputs in the output", CommandOptionType.NoValue); var hostConfigOption = app.Option("--host-config", "Specify a host config file", CommandOptionType.SingleValue); app.OnExecute(() => { FileStream outputFile = null; var writer = Console.Out; // Output to file instead of console if (optionOutput.HasValue()) { outputFile = File.Open(optionOutput.Value(), FileMode.Create); writer = new StreamWriter(outputFile); } // Get payload search path var payloadPath = pathArg.Value ?? "..\\..\\..\\..\\samples\\v1.0\\Scenarios"; if (pathArg.Value == null) { Console.WriteLine($"No path argument specified, trying {payloadPath}..."); } var files = new List <string>(); if (File.Exists(payloadPath)) { files.Add(payloadPath); } else if (Directory.Exists(payloadPath)) { var recurse = optionRecurse.HasValue() ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; files = Directory.GetFiles(payloadPath, "*.json", recurse).ToList(); Console.WriteLine($"Found {files.Count} card payloads..."); } else { Console.WriteLine($"{payloadPath} does not contain any JSON files. Nothing to do."); return; } writer.WriteLine(@"<!DOCTYPE html> <html> <head> <title>Adaptive Cards HTML Renderer Test Bed</title> <meta charset=""UTF-8""> <style type""text/css""> * { box-sizing: border-box; font-family: 'Segoe UI' } .cardcontainer { width: 400px; border-width: 1px; border-color: #808080; border-style: solid; } .error { border: solid 1px maroon; color: white; background: maroon; padding: 5px; width: 400px; } .warning { border: solid 1px orange; color: white; background: orange; padding: 5px; width: 400px; } </style> </head> <body>"); AdaptiveHostConfig hostConfig = new AdaptiveHostConfig() { SupportsInteractivity = optionSupportsInteracitivty.HasValue() }; if (hostConfigOption.HasValue()) { hostConfig = AdaptiveHostConfig.FromJson(File.ReadAllText(hostConfigOption.Value())); } AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(hostConfig); writer.WriteLine($"<h3>Renderer schema version: {renderer.SupportedSchemaVersion}</h3>"); writer.WriteLine($"<h4>Interactivty Enabled: {hostConfig.SupportsInteractivity}</h4>"); writer.WriteLine($"<h4>Generated at: {DateTime.Now:G}</h4>"); foreach (var file in files) { try { writer.WriteLine("<hr/>"); writer.WriteLine($"<h2>{Path.GetFileName(file)}</h2>"); AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(File.ReadAllText(file, Encoding.UTF8)); AdaptiveCard card = parseResult.Card; RenderedAdaptiveCard renderedCard = renderer.RenderCard(card); // Report any warnings foreach (var warning in parseResult.Warnings.Union(renderedCard.Warnings)) { writer.WriteLine($"<p class='warning'>WARNING: {warning.Message}</p>"); } writer.WriteLine($"<div class='cardcontainer'>{renderedCard.Html}</div>"); } catch (Exception err) { Debugger.Break(); writer.WriteLine($"<p class='error'>ERROR: {err.Message}</p>"); } } bool allowInlinePlayback = hostConfig.Media.AllowInlinePlayback; // Convert to JavaScript boolean values (False -> false, True -> true) string jsAllowInlinePlayback = allowInlinePlayback.ToString().ToLower(); writer.WriteLine("</body>"); writer.WriteLine($@" <script> // Sample JavaScript code to make media elements work const mediaPosterButtons = document.getElementsByClassName('ac-media-poster'); const allowInlinePlayback = false; for (var i = 0; i < mediaPosterButtons.length; i++) {{ const button = mediaPosterButtons[i]; button.addEventListener('click', function() {{ if ({jsAllowInlinePlayback}) {{ const mediaId = button.dataset.acMediaid; const mediaPlayerContainer = document.getElementById(mediaId); if (mediaPlayerContainer) {{ // Hide the poster button.style.display = 'none'; // Show the media player container mediaPlayerContainer.style.display = ''; // Play the media const mediaPlayer = document.getElementById(`${{mediaId}}-player`); mediaPlayer.play(); }} }} else {{ const mediaSources = button.dataset.acMediaSources; alert(mediaSources); }} }}); }} </script>"); writer.WriteLine("</html>"); if (outputFile != null) { writer.Flush(); outputFile.Flush(); outputFile.Dispose(); Console.WriteLine($"All cards were written to {outputFile.Name}"); } // if output, launch the file if (Debugger.IsAttached) { Console.ReadLine(); } }); return(app.Execute(args)); }