Workaround to Hero Card as attachment markdown formatting? - botframework

I know that markdown is supported on the HeroCard "text" field value, even though I couldn't make it work(Tested on MSTeams):
Code
this.bot.dialog("sendCard", (session, args, next) => {
session.sendTyping();
const card = new builder.HeroCard(session);
card.title("Title");
card.subtitle("Subtitle");
card.text("This is some *mardown* text! \n\n - one \n\n - two");
const msg = new builder.Message(session);
msg.textFormat("markdown");
msg.attachments([
card,
]);
session.endDialog(msg);
});
I am wondering how can I achieve this formatting(From mailclark bot in MSTeams):
As you can see, it is a carousel of what I think it might be HeroCards, but they are formatted with bold, code and unordered lists on new paragraphs.
It seems to be a known issue that message attachments do not receive formatting, but how could the mailclark guys achieve it?
Edit:
Unordered list example:
Bold and code example:

As Hero Cards eventually will be convert to Rich Card send to user from bot, and from MS Teams documents at https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-conversations#formatting-text-content:
Microsoft Teams supports a subset of Markdown and XML (HTML) formatting tags.
Rich cards do not support Markdown or table formatting
So in MS Teams channel, markdown formatting is only supported in text only message, however, we can leverage HTML tags in Rich Card.
Please consider following code snippet:
bot.dialog('/', function (session) {
const card = new builder.HeroCard(session);
card.title("Type your question to our support team here");
card.subtitle("Or, click the ◀▶ arrows for a series of how-tos");
card.images([builder.CardImage.create(session,"<image url>")])
card.text("<p>This is some <i>mardown</i> <b>text</b>!</p> <ul><li><b>one</b></li><li><code>two</code></li></ul>")
const msg = new builder.Message(session);
msg.attachmentLayout(builder.AttachmentLayout.carousel);
msg.attachments([
card,card,card
]).toMessage();
session.send(msg);
session.endDialog("This is some *mardown* **text**! \n\n - **one** \n\n - `two`");
});
This shows in MS Teams as following:

MailClark here. You're right: it's a carousel of Hero Cards.
As Gary said, it's mostly simple HTML with a few <code> and <strong> tags.
But this is the real secret: the list is not HTML it's just regular text and the 3 lines are starting with a good old bullet character: • (we didn't like the style produced by <ul><li>).

Related

How do I embed an image uploaded by form to google doc/auto generating PDF?

I have a google form (Medical report). Whenever someone answers the form, the answers go to a sheet and creates copy of a doc template, replaces keywords and then generates a pdf. I've create separate folders to organize the PDFs for the responses. This is working well thus far.
However, the report (Google Form) requires the user to upload an image as part of some of the answers (Sample Form Layout). I would like to have two separate images automatically appear on the doc for Before Treatment and After Treatment (To replace the sample text from google doc with pictures).
The image uploads to drive fine, but I don't know how to have the uploaded image appear on the Google docs and pdf. So far I'm only able to obtain a drive link instead of an actual image (How the PDF generated file looks like)
Here's a sample of my script:
Function afterFormSubmit(e) {
const info = e.namedValues;
//Running the createPDF fuction into the form submission
createPDF(info);
}
//Function to create PDF
function createPDF(info){
const pdfFolder = DriveApp.getFolderById("pdfFolderId");
const tempFolder = DriveApp.getFolderById("tempFolderId");
const templateDoc = DriveApp.getFileById("docTemplateId");
//Get ID of file and open as a document
const OpenDoc = DocumentApp.openById(newTempFile.getId());
const body = OpenDoc.getBody();
//Get body from the PDF text and replace the keywords based on the response submission
body.replaceText("{name}", info['Patient Name'][0] );
body.replaceText("{report no}", info['Report No'][0]);
body.replaceText("{before}", info['Before Treatment Image'][0]);
body.replaceText("{after}", info['After Treatment Image'][0]);
OpenDoc.saveAndClose();
//Creating a file name based on the report no
const blobPDF = newTempFile.getAs(MimeType.PDF);
const PdfFile = pdfFolder.createFile(blobPDF).setName(info['Report No'][0]])
tempFolder.removeFile(newTempFile);
}

Bold text not showing in hero cards

I'm having some problems with bold text in hero cards, currently I build my hero card like so:
var workloadCard = new HeroCard
{
Title = $"Partido #{number+1}",
Subtitle = $"**{matches[number].equipo1} vs {matches[number].equipo2}**",
Text = ($"El {fecha.ToString("dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture)} a las: \nMéxico: **{matches[number].hora.Replace(" ", "")}** \nRusia: **{horaRUs}** \nEn {matches[number].sede}"),
Images = new System.Collections.Generic.List<CardImage> { new CardImage($"{url}") },
Buttons = cardButtons,
};
The problem is that the text between ** ** is shown with asterisks instead of being bold:
$"**{matches[number].equipo1} vs {matches[number].equipo2}**
Turns into
**México vs Suecia**
Instead of
México vs Suecia
This happens in any part of the hero card but otherwise works in flat responses, what is the cause of this and how can I fix it?
Hero cards accept html tags inside them so I fixed this problem by doing this:
$"<b>{matches[number].equipo1} vs {matches[number].equipo2}</b>
Instead of this:
$"**{matches[number].equipo1} vs {matches[number].equipo2}**

How to get the entire Visual Studio active document... with formatting

I know how to use VS Extensibility to get the entire active document's text. Unfortunately, that only gets me the text and doesn't give me the formatting, and I want that too.
I can, for example, get an IWpfTextView but once I get it, I'm not sure what to do with it. Are there examples of actually getting all the formatting from it? I'm only really interested in text foreground/background color, that's it.
Note: I need the formatted text on every edit, so unfortunately doing cut-and-paste using the clipboard is not an option.
Possibly the simplest method is to select all of the text and copy it to the clipboard. VS puts the rich text into the clipboard, so when you paste, elsewhere, you'll get the colors (assuming you handle rich text in your destination).
Here's my not-the-simplest solution. TL;DR: you can jump to the code at https://github.com/jimmylewis/GetVSTextViewFormattedTextSample.
The VS editor uses "classifications" to show segments of text which have special meaning. These classifications can then be formatted differently according to the language and user settings.
There's an API for getting the classifications in a document, but it didn't work for me. Or other people, apparently. But we can still get the classifications through an ITagAggregator<IClassificationTag>, as described in the preceding link, or right here:
[Import]
IViewTagAggregatorFactoryService tagAggregatorFactory = null;
// in some method...
var classificationAggregator = tagAggregatorFactory.CreateTagAggregator<IClassificationTag>(textView);
var wholeBufferSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, 0, textBuffer.CurrentSnapshot.Length);
var tags = classificationAggregator.GetTags(wholeBufferSpan);
Armed with these, we can rebuild the document. It's important to note that some text is not classified, so you have to piece everything together in chunks.
It's also notable that at this point, we have no idea how any of these tags are formatted - i.e. the colors used during rendering. If you want to, you can define your own mapping from IClassificationType to a color of your choice. Or, we can ask VS for what it would do using an IClassificationFormatMap. Again, remember, this is affected by user settings, Light vs. Dark theme, etc.
Either way, it could look something like this:
// Magic sauce pt1: See the example repo for an RTFStringBuilder I threw together.
RTFStringBuilder sb = new RTFStringBuilder();
var wholeBufferSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, 0, textBuffer.CurrentSnapshot.Length);
// Magic sauce pt2: see the example repo, but it's basically just
// mapping the spans from the snippet above with the formatting settings
// from the IClassificationFormatMap.
var textSpans = GetTextSpansWithFormatting(textBuffer);
int currentPos = 0;
var formattedSpanEnumerator = textSpans.GetEnumerator();
while (currentPos < wholeBufferSpan.Length && formattedSpanEnumerator.MoveNext())
{
var spanToFormat = formattedSpanEnumerator.Current;
if (currentPos < spanToFormat.Span.Start)
{
int unformattedLength = spanToFormat.Span.Start - currentPos;
SnapshotSpan unformattedSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, currentPos, unformattedLength);
sb.AppendText(unformattedSpan.GetText(), System.Drawing.Color.Black);
}
System.Drawing.Color textColor = GetTextColor(spanToFormat.Formatting.ForegroundBrush);
sb.AppendText(spanToFormat.Span.GetText(), textColor);
currentPos = spanToFormat.Span.End;
}
if (currentPos < wholeBufferSpan.Length)
{
// append any remaining unformatted text
SnapshotSpan unformattedSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, currentPos, wholeBufferSpan.Length - currentPos);
sb.AppendText(unformattedSpan.GetText(), System.Drawing.Color.Black);
}
return sb.ToString();
Hope this helps with whatever you're doing. The example repo will ask if you you want the formatted text in the clipboard after each edit, but that was just a dirty way that I could test and see that it worked. It's annoying, but it was just a PoC.

Attribute concatenation with multiple Theme Classes in SD app

I am creating a SD App in GX Ev3, and am working on a list.
I came across a requirement for the App and don't know how to do it.
I have to concatenate some Attributes in a String, but one of them (&Status) has to be Font Bold.
&Status + ', por ' + &User + ' em ' + &Date
Possible results:
'OK, por User1 em 01/07/2014'
'Com problema #5, por User2 em 01/07/2014'
'Por validar, por User3 em 01/07/2014'
How can I do it, so it looks like continuous text?
You can do that by using a variable based on the Html domain, and using HTML formatting for the value (i.e. "<b>OK</b>, por ...").
This will create a WebView to display the text, achieving the effect you want.
However, WebViews are unfortunately more resource-intensive than edits, so using them inside a grid is not recommended. We hope to provide a better solution soon.
I would do the HTML field as matiash suggested
But if you want other solution you could do a User Control that can help you.
In an application we have been developing for iOS we have done this using the NSAttributeString.
https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/classes/NSAttributedString_Class/Reference/Reference.html
What we did is:
&varUC = "#"+&Status +"# my middle text 1 #" + &User + "# my middle text2 #"+&Date+"#"
In our UC we separated the string by the "#" and we changed the the color and weight of those words, then remove the # when displaying the text.
For Android, we haven't done this yet, but with a quick Google search I think you should use:
how to change text color in the middle of the sentence in android
Doing a User Control for GeneXus Smart Devices is really easy ->
http://wiki.genexus.com/commwiki/servlet/hwikibypageid?15301
You can try using the tag "after" in the definition of the class, but you'll have to split the atribute.
Your best bet is to split the variables on the screen, both with distinct classes:
&Status &Text
&Status = 'OK'
&Text = ', por'+&User+' em '+&date
The css sample below is used to automatically set bold fields and (*) on the label of required fields:
.RequiredDataDescription:after
{
font-size: 11px;
font-weight: bold;
color: #333333;
content:" (*)";
}

Arabic font in Web UI and itextsharp

I'm not able to find a reason why my MVC 3 web site shows arabic font correctly and my pdf not.
I use a bliss font in my web site;
#font-face {
font-family: 'blissregular';
src: url('/Fonts/blissregular-webfont.eot');
src: url('/Fonts/blissregular-webfont.eot?#iefix') format('embedded-opentype'),
url('/Fonts/blissregular-webfont.ttf') format('truetype');
font-weight: normal;
font-style: normal;}
All working fine.
After that I want to create the pdf of the output but arabic fonts does not appears.
I've googled and understand that the font must have the arabic character to show up correctly. I've changed to arial font (that contains arabic character) and... pdf worked.
So... How is possible that with bliss font (that does NOT have arabic characters) I see arabic font in web site?
I'm really confused....
thanks a lot to everybody!
For every character your browser encounters it looks for a matching glyph in the current font. If the font doesn't have that glyph it looks for any fallback fonts to see if they have that glyph. Ultimately every browser has a core set of default fonts that are the ultimate fallback. When you specify the font Bliss but use Arabic characters you are probably just seeing your browser's fallback fonts.
PDFs don't work that way. If you say something is using font XYZ then it will try to render it using that font or fail.
The easiest way probably is to just add a font to your CSS that supports those characters.
.myclass{font-family: blissregular, Arial}
If that doesn't work you might need to inject the fonts manually. (Actually, I'm not 100% certain the iText support #font-face, either.) iText has a helper class that can figure things out for you that Bruno talks about it here but unfortunately the C# link isn't working anymore. It's very simple, you just create an instance of the FontSelector class, call AddFont in the order that you want characters to be looked up up in and then pass a string to the Process() method which spits back a Phrase that you can add. Below is basic sample code that shows this off. I apologize for my sample text, I'm English-native so I just searched for something to use, I hope I didn't mangle it or get it backwards.
You'll need to jump through a couple of extra hoops when processing the HTML but you should be able to work it out, hopefully.
//Sample string. I apologize, this is from a Google search so I hope it isn't backward
var testString = "يوم الاثنين \"monday\" in Arabic";
var outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Test.pdf");
//Standard PDF setup
using (var fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
//This is a font that I know *does not* support Arabic characters, substitute with your own font if you don't have it
var gishaFontPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "gisha.ttf");
var gishaBaseFont = BaseFont.CreateFont(gishaFontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
var gishaFont = new iTextSharp.text.Font(gishaBaseFont, 20);
//Add our test string using just a normal font, this *will not* display the Arabic characters
doc.Add(new Phrase(testString, gishaFont));
//This is a font that I know *does* support Arabic characters
var arialFontPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "ARIALUNI.TTF");
var arialBaseFont = BaseFont.CreateFont(arialFontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
var arialFont = new iTextSharp.text.Font(arialBaseFont, 20);
//Create our font selector specifying our most specific font first
var Sel = new FontSelector();
Sel.AddFont(gishaFont);
Sel.AddFont(arialFont);
//Have the font selector process our text into a series of chunks wrapped in a phrase
var newPhrase = Sel.Process(testString);
//Add the phrase, this will display both characters
doc.Add(newPhrase);
//Clean up
doc.Close();
}
}
}

Resources