Hey everyone! I created a new tool that creates fancy SVG based indicators that dynamically update based on an assigned percent complete column in your app.
SVG stands for Scaleable Vector Graphics and these file types are special in that they are infinitely scaleable. Instead of being made of pixels like a regular image type, they are made from vectors, rays, circles, paths, etc so you can make the image as large (or small) as you need and the device will render these graphics on the fly in real-time without any quality loss.
Because SVG graphics are rendered in real-time we can create indicators that update dynamically as the value of another column changes. These images can be used as headers in โdetailโ views, inline images in your โtableโ views or an image in your โdeckโ view. Below are just a few examples:
I have made this tool available as a sample app that can be found at the link below:
Here are some quick tips to get started:
Enter the name of the โpercent column typeโ you will be using in your app into the DIM tool.
Select whether you want a circle, horizontal bar or vertical indicator.
Adjust the corners of your indicator using the sliders provided.
Change the colors of the indicator based on your preferences (you need to use hex codes, click the pallet icon above this section to open up htmlcolorcodes.com. You can adjust the progress color, background color and the text color.
As you make these selections, you can view a realtime preview of the indicator you are making at the top of the screen*.
When you are happy with the look, simply copy the formula provided at the bottom (or right side of the screen if in full screen) and create an โimage type virtual columnโ in your app with the formula provided.
There are many more opportunities with this idea. I would love to see if anyone from the community can take this idea and make it even better. Please copy!
*while the app will show that values are trying to sync, this has no effect on what you see on the screen. All calculations are handled via virtual columns so all results/changes are instant.
Cool tool! Super useful
@Grant_Stead @Suvrutt_Gurjar @Fabian @Rich
One thing you might consider adding is dynamic svg thumbnails as a substitute for the native THUMBNAIL() function which relies on external thumbnail services. A simple thumbnail could be:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80">
<rect width="100%" height="100%" fill="rgb(67, 135, 191)"/>
<text font-family="Sans-Serif" font-size="35px" text-anchor="middle" fill="white" x="50%" y="65%">JS</text>
</svg>
Which would render as:
You could also get creative to create more rich dynamic thumbnails, such as highway placards:
One limitation of AppSheet that can be solved with SVGโs is the creation of dynamic form headers/text or animations within forms. AppSheets format rules are applied upon initiating the form view - they DO NOT recalculate upon changing values in a form until after the form is saved.
For example, you might want text to show up as โEverythings Good!โ in green, and then change to โWarning!โ as red depending on specified values. Currently, the text will change, but the format rules which dictate its color will not. To get the desired behaviour without SVGโs appsheet requires two virtual columns that are preformatted, and SHOW() rulesets to hide one or the other.
I have also used SVGโs in applications to display dynamic images in forms. One example is modifying an excavator to appear to be digging further down / deeper as a user adjusts a numerical range column indicating depth. Another example is highlighting portions of serialized text as users input it:
You can read about how to create SVG pie charts here:
This is an awesome helpful tool. Thank you very much @Rich
Here are some Ideas:
fill=""rgb(88,89,91)""
text font-family
according to the fonts AppSheet offers under UX --> OPTIONS --> FONTSThanks @Fabian for the feedback. Good catch Ill be sure to update to app!
These were left in the app for future development, I wanted to give the option for folks to define the dimensions of the image instead of being static. For example you may want a horizontal bar that is thinner or thicker
@Grant_Stead You are right it was a pain to test these, iOS was very finicky. However, I have tested all the SVG options with apps iOS, PC, Mac, Android and in Chrome and Safari browsers. That said, if anyone sees an issue with other browsers Ill be sure to take a look at it.
Thanks a lot for this handy tool, @Rich_E! Is there a version of the sample app where the fix for the text color in the circle indicator was applied? The sample app version linked from the original post still has that issue.
This is amazing! Thank you.
Ok, Iโm curious.
There was a massive thread in which @Jonathon and @Fabian really went back and forth on this, they even started a community based app with another member. This is how I learned about itโฆ
One of the reasons I donโt use SVG is because it didnโt seem stable on different devices. Has appsheet fixed that, and SVG is better supported now?
This is awesome and makes creating the code for these indicators wicked easy!!
For colors, the app could include @Fabian color mixer found here:
Thank you @Rich. The DIM app is very neat with various settings that user can make to create an indicator of oneโs chosen type , color choice and few other options. These indicators will make the app user experience much richer and certainly have numerous use cases wherever progress, status needs to be shown in the app.
Would appreciate further insights by you all - @Rich, @Jonathon and @Fabian on the points mentioned by @Grant_Stead as to how these SVG based indicators will render on various devcies.
Unless something has changed recently, the current limitations of SVGโs in AS are:
I will edit this as I think of more.
You could work around some of these limitations with a user setting (display enhanced graphics option, and then include a warning about not working on older browsersโฆ)
Thank you @Jonathon. Your insights are very useful as usual.
Oh thatโs a shame, thank you anyway Fabian! I have been looking at an idea to show graphs in my reports using the script in google docs script tools but I donโt know how to connect the Gdocs script tools with appsheet workflow report generator. Any idea on work around to maybe save an SVG to PNG to a Gdrive folder and the showing that pre saved image in the report. Any idea is welcome!
@Felipe_Engelberger_A Using Integromat and Cloud Convert Service as explained here. (instead of converting PDF in your case you convert SVG)
If no one else has come across this, I thought I would share. I (so far) have successfully imported a font for use in rendering SVGs in AppSheet. This can be done by converting the font to Base64:
"data:image/svg+xml;utf8,<svg xmlns=""http://www.w3.org/2000/svg"" viewBox=""0 0 100 50"">
<defs>
<style type=""text/css"">
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url(data:application/font-woff;charset=utf-8;base64, <...YOUR BASE64 CODE HERE...>) format('woff');
}
</style>
</defs>
<text font-family=""Roboto"" ...other settings... >"&
[Your Text]
&"</text>
</svg>"
Replacing all of <โฆYOUR BASE64 CODE HEREโฆ> with your actual Base64 code from the converted .WOFF file. I literally canโt show it here as it exceeds the maximum size limitations of a single post.
I think everything is double quoted correctly. I canโt test it on everything though, so feel free to let me know if this doesnโt work for other browsers/devices. As a proof of concept:
Default
vs
Roboto
The reason for this is because when the views are laid out the image is placed inside an HTML <img>
tag which kills the ability to link to an external google font all easy peasy - appropriately as a security measure within the HTML itself. The downside being that this method can seriously impact rendering time and trying to navigate the editor with that giant string is a pain (did all the work in notepad).
Edit: After some testing between a VC and regular image column (and ~3000 rows) with the embedded font in the SVG, the performance difference is negligible (within 2 seconds of each other). Average full sync time: 45 seconds. Of which, I only force a full sync at specific moments (and might be able to completely eliminate).
And to make the editor less likely to struggle, I threw the Base64 code into a separate table so I can just grab it. This will, of course, also facilitate the use of multiple fonts if I so choose.
Super cool thanks
Thatโs awesomeโฆ
So then youโre kinda posting the โofficialโ Appsheet has tested and approves these specific SVG expressions to be used? โBut, disclaimer SVG is still garbage town in internet explorer/Edge. But Appsheet doesnโt โreallyโ support these anywayโฆโ
One way AppSheet could help eliminate internet explorer use (sorry MSFT) is by making it easier for app developers to deploy progressive webapp installers for Chrome.
Thanks for sending me to my google machineโฆ
Yep. If a browser supports SVG then I will see if I can fix any compatibility issues.
I was so excited about this App that I thought it should be possible to built an own Color Picker.
I already made this Color Picker for RGB, but I thought thatโs not very handy.
So here you go
@Fabian That is awesome! You guys are so creative!
Dude, this is insanely creative!
@Fabian that is awesome! Amazing idea. When you have it ready to go, DM me and ill update the sample app.
Keep the ideas coming!
Hi @Rich Please feel free to grab the Color Picker from my App:
appName=DynamicIndicatorMaker-549987
Thanks for all these wonderful ideas and explanations. This is a very supportive community with a great archive.
Is @Fabian_Weller's color picker incorporated into @Rich_E's DIM or otherwise shared somewhere? I'm not finding it in the sample app linked from the original post nor among the other links in this conversation.
@dbaum I put it on my Portfolio Page
Found it. Thanks for sharing!
This is great! It opens so many doors.
Iโm having problems making it work on some browsers: Firefox (show only when click the image - desktop and mobile) and Edge (doesnt show at all).
It works perfectly on Chrome.
Hi Hugo - admittedly my testing of firefox has been minimal, but when I last checked my SVGโs were working in that browser.
Care to share your svg code so I can rule out anything obvious?
Jon
Ill check into the Firefox issue. Not much I can do with Edge at this time. Last I check they had poor support of SVGs.
Cool looking tool. I think something is wrong though. Hereโs what I see. On Firefox here, and just updated this morning.
Iโm facing this exactly same problem on Firefox with any SVG, even on the DIM app. The SVG image appears briefly when I click on the blank box.
Interesting. Just doing some testing of my applications on Firefox now. All SVGโs are working, but some are missing elements:
In my case it appears FireFox does not like a certain pattern of <Path>
that render fine in other browsersโฆ
I suspect there is some element in the SVGโs generated by the DIM app that firefox is offended by, but it is certainly fixable. My radial progress bars/etc are working in FF.
Hi everyone do you have an idea on how can I insert one of the SVG graphs into a GoogleDocs Template report? Thank you in advance
You should be able to just add the virtual column into the template just like any other image.
Oh I understand, when I tried adding the virtual column I got the following error when I try to generate the PDF report, any idea on what Iโm doing wrong? Thanks
Error: โSystem.Exception: Failed to remove file extension from file name 'data:image/svg+xml;utf8, <svg xmlns=โhttp://www.w3.org/2000/svgโ viewBox=โ0 0 170 30โ> \n\n\n <linearGradient id=โgrad1โ x1=โ0%โ y1=โ0%โ x2=โ100%โ y2=โ0%โ>\n <stop offset=โ0%โ style=โstop-color:%23008CE9;stop-opacity:1โ />\n <stop offset=โ100%โ style=โstop-color:%23008CE9;stop-opacity:1โ />\n \n \n<rect x=โ10โ y=โ5โ rx=โ13โ ry=โ10โ width=โ150โ height=โ20โ stroke=โblackโ fill=โ%23F3F3F3" />\n\n\n <rect x=โ10โ y=โ5โ rx=โ13โ ry=โ10โ width=โ94.5โ \n\nheight=โ20โ stroke=โblackโ fill=โurl(%23grad1)โ stroke-opacity=".5" />\n\n<rect x=โ10โ y=โ5โ rx=โ13โ ry=โ10โ width=โ150โ height=โ20โ stroke=โblackโ stroke-width = โ2โ fill=โnoneโ />\n\n<text font-family=โRoboto,Arial,sans-serifโ font-size=โ20pxโ font-weight=โ300โ stroke-width=โ5โ text-anchor=โmiddleโ fill="%23000000" x=โ50%โ y=โ22โ>21%\nโ because it contains Invalid characters: โ"โ (Hex Character โ0022โ) โ<โ (Hex Character โ003Cโ) โ>โ (Hex Character โ003Eโ) โwhite space characterโ (Hex Character โ000Aโ) \r\n at Nirvana.Data.TemplateUtilities.GetFileNameWithoutExtension(String path) in d:\a\1\s\V2API\Workflow\Template\TemplateCommon\TemplateUtilities.cs:line 208\r\n at Nirvana.Data.ReplaceTemplateExpressions.ConstructImageValue(Context context, AppType appType, String src, String tableName, AllowedFormatSettings formatSettings) in d:\a\1\s\V2API\Workflow\Template\TemplateExpression\ReplaceTemplateExpressions.cs:line 172\r\n at Nirvana.Data.ReplaceTemplateExpressions.GetExpressionReplacementValue(Context context, WorkflowTemplateBindContext bindContext, TemplateExpression templateExpression, String tableName, Int32 columnSliceMapping, Change change, AppDataContext appDataContext, UpdateModeEnum updateMode, EmailExpressions emailExpressions) in d:\a\1\s\V2API\Workflow\Template\TemplateExpression\ReplaceTemplateExpressions.cs:line 503\r\n at Nirvana.Data.ReplaceTemplateExpressions.Replace(Context context, WorkflowTemplateBindContext bindContext, String templateText, TemplateExpressions templateExpressions, String tableName, Int32 columnSliceMapping, Change change, AppDataContext appDataContext, UpdateModeEnum updateMode, EmailExpressions emailExpressions, AppErrors appErrors) in d:\a\1\s\V2API\Workflow\Template\TemplateExpression\ReplaceTemplateExpressions.cs:line 677\r\n at Nirvana.Data.TemplateHtml.ReplaceTemplateExpressions(Context context, WorkflowTemplateBindContext bindContext, XElement rootElement, String tableName, Int32 columnSliceMapping, Change change, AppDataContext appDataContext, UpdateModeEnum updateMode, EmailExpressions emailExpressions, AppErrors appErrors) in d:\a\1\s\V2API\Workflow\Template\TemplateHtml\TemplateHtml.cs:line 53\r\n at Nirvana.Data.TemplateHtml.Replace(Context context, WorkflowTemplateBindContext bindContext, String tableName, Boolean compatibilityMode, Int32 columnSliceMapping, Change change, AppDataContext appDataContext, UpdateModeEnum updateMode, EmailExpressions emailExpressions, Templates templates, AppErrors appErrors) in d:\a\1\s\V2API\Workflow\Template\TemplateHtml\TemplateHtml.cs:line 82\r\n at Nirvana.Data.TemplateHtml.Replace(Context context, WorkflowTemplateBindContext bindContext, String tableName, Boolean compatibilityMode, Int32 columnSliceMapping, Change change, UpdateModeEnum updateMode, EmailExpressions emailExpressions, Templates templates, AppErrors appErrors) in d:\a\1\s\V2API\Workflow\Template\TemplateHtml\TemplateHtml.cs:line 273\r\n at Nirvana.Data.Templates.Replace(Context context, WorkflowTemplateBindContext bindContext, String tableName, Int32 columnSliceMapping, Change change, UpdateModeEnum updateMode, EmailExpressions emailExpressions, AppErrors appErrors) in d:\a\1\s\V2API\Workflow\Template\TemplateCommon\Templates.cs:line 74\r\n at Nirvana.Data.WorkflowTemplate.Replace(Context context, Int32 columnSliceMapping, Change change, UpdateModeEnum updateMode, EmailExpressions emailExpressions, AppErrors appErrors) in d:\a\1\s\V2API\Workflow\Template\WorkflowTemplate\WorkflowTemplate.cs:line 686\r\n at Nirvana.Data.WorkflowActionEmail.GetAttachment(Context context, String tableName, Int32 columnSliceMapping, Change change, UpdateModeEnum updateMode, EmailExpressions emailExpressions, AppErrors appErrors) in d:\a\1\s\V2API\Workflow\Action\WorkflowActionEmail.cs:line 228\r\n at Nirvana.Data.WorkflowActionEmail.Create(Context context, String tableName, Int32 columnSliceMapping, Change change, UpdateModeEnum updateMode, ActionDefinition actionDefinition, WorkflowLogEvent workflowLogEvent) in d:\a\1\s\V2API\Workflow\Action\WorkflowActionEmail.cs:line 49\r\n at Nirvana.Data.WorkflowRuleEvaluator.CreateActionResults(Context context, WorkflowActionBase workflowAction, AppTemplate appTemplate, String tableName, Int32 columnSliceMapping, Change change, UpdateModeEnum updateMode, WorkflowLogEvent workflowLogEvent) in d:\a\1\s\V2API\Workflow\Evaluators\WorkflowRuleEvaluator.cs:line 126\r\n at Nirvana.Data.WorkflowRuleEvaluator.PerformActions(Context context, AppTemplate appTemplate, String tableName, Int32 columnSliceMapping, Change change, UpdateModeEnum updateMode, WorkflowLogEvent workflowLogEvent) in d:\a\1\s\V2API\Workflow\Evaluators\WorkflowRuleEvaluator.cs:line 355\r\n at Nirvana.Data.WorkflowRuleEvaluator.ProcessRule(Context context, String tableName, Int32 columnSliceMapping, Change change, UpdateModeEnum updateMode) in d:\a\1\s\V2API\Workflow\Evaluators\WorkflowRuleEvaluator.cs:line 492"
Based on this part of the message it seems some of the characters used in the code are not considered valid. I would take a very careful look at how you have built the string - especially at the placement of quotations.
By the way, Does the Virtual Column show the information correctly?
yes it works perfectly
Really amazing @Rich thanks