Fins Extension

When enable finHtmlReporting extension (download finHtmlReporting.zip ), following axon functions will be available for usage:

finHtmlTemplate( noteTemplate, data, renderEmail := false)

accepted parameters:

noteTemplate: this can be a valid handlebar template string, or a record to io bin file or a tag of a record that has property "tpl" holding the handlebars template string
data : can be result of an axon call such as readAll(site) or a map {key:value}
renderEmail: true if you need to convert the return into html email body. this is useful when sending html email with inline attached images. The email body will be in multi-part format.


This function will read the template and use handlebars.java (http://handlebars.java/blog) engine to render the template with given data. Handlebars has a cool feature to let user define extra helpers. A helper defines how a template will behave on specific data.

Built-in helpers are defined at http://handlebarsjs.com/builtin_helpers.html.

The extension provide additional helpers such as collections http://assemble.io/helpers/helpers-collections.html , numbers http://assemble.io/helpers/helpers-numbers.html

and following custom filters:

1){{embedImg}} helper : helper to embed image and construct inline image for html email
Syntax: {{embedImg url_or_@id maxWidth? maxHeight?}}

example:<pre> <img src="{{embedImg @id}}"/> or <img src="{{embedImg http://....}}"/>

    will output : <img src="cid:xxxxxx.12312312@j2inn.com"/>


2){{#is}} helper acts like {{#if}}, comparison utility

Syntax:   {{#is param1 param2 operand}}...{{else}}...{{/is}}

   Given one argument, is acts exactly like if: {{#is x}}..{{else}}..{{/is}}
   Given two arguments, is compares the two are equal 
         (a non-strict, == comparison, so 5 == '5' is true) 
         {{#is x y}} ... {{else}} ... {{/is}}
   Given three arguments, the 3rd argument becomes the comparator.
   {{#is x y "not"}} ... {{else}} ... {{/is}}
   {{#is 5 2 ">="}} ... {{else}} ... {{/is}}
   Several comparators are built-in: 
     == (same as not providing a comparator)
      not (alias for !=)
      in (check a value exists in either a comma-separated string, or an array)

3) hfilter https://bitbucket.org/brianfrank/haystack-java/

with improved lookup rules

Lookup in the query sheMale and idRef->male      
Lookdown in the query female and subObject->tom
*ahuRef->ahu  //// Try and find every record that has a ahuRef, and see if he is an ahu
*foo -> curVal > 10  //// If foo looks like this  {"curVal":8,"ahu","jason"}. Then this would return true
*foo -> curVal > 10 //// [{"curVal":3,"ahu","jason"},{"curVal":12,"ahu","jason"}]. This would return true, 
     because one of the objects in the list is > 10
*If foo is a list without any keys, it will just return false.  [1,23,5,5,6,6,7]   

{{#hFilterEach}} : filter the collection using hfilter, similar to {{#each}}

Syntax: {{#hFilterEach data expression}}..{{/hFilterEach}}

Example: {{#hFilterEach this "sheMale and subObject->foo" }} name: {{lastName}} {{/hFilterEach}}

4){{numberToTickerImages 4104}} or {{numberToTickerImages 4104 'small'}}

should render

<img src='http://email-assets.j2inn.com/images/ticker-numbers/ticker-4-small.png'><img src='http://email-assets.j2inn.com/images/ticker-numbers/ticker-1-small.png'><img src='http://email-assets.j2inn.com/images/ticker-numbers/ticker-0-small.png'><img src='http://email-assets.j2inn.com/images/ticker-numbers/ticker-4-small.png'>
{{numberToTickerImages 4104 'large'}}

should render

<img src='http://email-assets.j2inn.com/images/ticker-numbers/ticker-4-large.png'><img src='http://email-assets.j2inn.com/images/ticker-numbers/ticker-1-large.png'><img src='http://email-assets.j2inn.com/images/ticker-numbers/ticker-0-large.png'><img src='http://email-assets.j2inn.com/images/ticker-numbers/ticker-4-large.png'>

To ease the testing of user's handlebars template , there are utility functions

1) finSaveAs(uri, content): uri is the path to local file that content will be saved to

2) finEmail(toAddress, subject, emailBody): this will wrap the email body and send to given address. The smtp config is hard-coded using server: localhost and port:25.

To use this function you need to have smtp server listen on localhost port 25. The setting in finstack for email will not effect this function. For a free tool , try papercut .


Pass the template directly as function's parameter

finHtmlTemplate("hello {{name}}",{"name":"PersonName"}) -> hello PersonName


<!DOCTYPE html><html lang=""><head> <meta charset="utf-8">  <title></title></head>

<body><table><th>    <td>id</td>    <td>geoAddr</td></th>    {{#each this}}<tr>    <td>@{{id}}</td>    <td>**{{geoAddr}}**</td></tr>    {{/each}}</table></body>

</html>", readAll(site))

will return

<!DOCTYPE html><html lang=""><head> <meta charset="utf-8"> <title></title></head><body><table><th> <td>id</td> <td>geoAddr</td></th> <tr> <td>@Gaithersburg</td> <td>*18212 Montgomery Village Ave, Gaithersburg, MD</td></tr> <tr> <td>@ShortPump</td> <td>11282 W Broad St, Richmond, VA</td></tr> <tr> <td>@Headquarters</td> <td>600 W Main St, Richmond, VA</td></tr> <tr> <td>@Carytown</td> <td>3504 W Cary St, Richmond, VA*</td></tr> </table></body></html>

Using tag

Create a tag "simple_handlebar" with property "tpl" holding above template string

run the command : finHtmlTemplate("simple_handlebar",readAll(site)) will result

Using an uploaded file

Upload the above template

run the command :finHtmlTemplate("@1c588487-2e5416e3",readAll(site)) will return the same html as above

Everything is summarized here simple_handlebar.avi

Demo of multiple image template



Data passed to the function is from the call :readAll(site), in the template it uses helper {{embedImg imageRef.id}} to embed the image of the site in the email

command: finEmail("aaaa@j2inn.com","handlebar images",finHtmlTemplate("@1c58b274-c693093b",{title:"multiple images",imgs:readAll(site)},true))

@1c58b274-c693093b is the file hold the template

imgs : property of the data this, each site has properties :dis, and imageRef. imageRef is a Ref and {{embedImg}} takes a string as its parameter so you need to use imageRef.id which is like @xxxxxxxx-xxxxxxxx

The email will look like this

Render the template to email body

3rd parameter of finHtmlTemplate when set to true will return EmailPart instance that will be used to in sending emails using the finEmail() function or subscription email notification. By default it will return plain-text body if the template is not html-compliant. Otherwise it will return multipart body. To ease the deployment of the email template that can have other assets such as images, user can create a zip

main.html - is the template for html part

alternative- is the template for plain-text part - a fallback of html content

imgs- associated resources folder, which is referenced in the template

Video how to use zip file simple_zip.zip , simple_zip.avi

Email Templates

Old video : simple_email_template.avi

Sample template : simple_immediate_email .hdb

For notes

Create a record

in which:
noteTopic is the marker indicating this setting is for note topic email
emailTemplate: marker indicating this is for email template
imageRef: reference to the background image (IO file , need to upload your custom image first)
logoRef: refence to the logo image (customer logo, IO file)
immediateTemplateRef: reference to record that hold the template (see the first paramter of finHtmlTemplate). This template will be used to generate immediate email notification
digestTemplateRef: reference to record that hold the template (see the first paramter of finHtmlTemplate). This template will be used to generate digest email notification

For alarms

digestTemplateRef/immediateTemplateRef is a fileRef as well as a ref to a row with a 'tpl' property
some additional data to make the alarms digest.
Here's the list:
Hero background image url (set by imageRef),
Customer logo url (set by logoRef),
Month, Day, Year (pretty formatted (for locale) like you see below)
Weather: {
    weather image/icon
    high temp
Total alarms, 
For Each Alarm: {
    Equipment graphic image url 
    Time graph (see example data. Use parseDiscretePeriods, see: http://www.skyfoundry.com/doc/ext-his/funcs)
    Time (duration) in alarm for
    # times in alarm

The Time Graph is tricky. 
First off, in case you haven't seen it, the digest looks like this:
The "time graph" is the bars of red representing the points at which the alarm was active during that day.
The HTML for it looks like this:
<table class='timegraph'>
        {{#each timeGraph}}
            {{#if on}}
                <td class='on' width="{{width}}"></td>
            {{#if off}}
                <td class='off' width="{{width}}"></td>
so the JSON would end up being something like this:

  "timegraph": [
        {on: true, width: 15},
        {off: true, width: 15},
        {on: true, width: 15},
        {off: true, width: 15},
        {on: true, width: 15},
        {off: true, width: 15},
        {on: true, width: 15},
        {off: true, width: 15},
        {on: true, width: 15},
        {off: true, width: 15}
        (might be more, might be less)
All of the widths have to add up to 150 total, so you'd need to make a little function that converts the total number of on/off events and renders each row with a width that matches the ratio to the real time it was on.
Sample data : alarms.json