Introduction
If you need to add a field at runtime or change its content, you can use the field processor inside a source.
Field processors are based on handlebars and allow you to use simple methods for manipulating fields.
Field processors can be used inside a source and can either create a new field, or overwrite an existing.
Create a new field (excerpt):
sources: source: - id: 'MySource' fieldProcessor: - field: MyNewField value: '{{sourceValue}}'
Overwrite an existing field (excerpt):
sources: source: - id: 'MySource' fieldProcessor: - field: MyExistingField value: '{{MyExistingField}}-SOME_SUFFIX'
It is very advisable to use parantheses inside the configuration for handlebar values:
Good Practice:
fieldProcessor: - field: MyExistingField value: '{{MyExistingField}}-SOME_SUFFIX'
Bad Practice:
fieldProcessor: - field: MyExistingField value: {{MyExistingField}}-SOME_SUFFIX
Inside an ELO source, handlebars can also be used inside maps/tables - see below examples.
Nesting/Combination of multiple Functions
You can nest multiple functions using “()”
Example:
- field: CLOSE_TO_EXPIRATION value: '{{#if (gt (remainingTimeUnit (currentDateTime) (parseDateTime P_LICENSE_M_VALID_TO "yyyy-MM-dd") "days") 30)}}false{{else}}true{{/if}}'
equivalents pseudocode:
function CLOSE_TO_EXPIRATION(): currentDateTime = currentDateTime() #First Helper parsedDateTime = parseDateTime(P_LICENSE_M_VALID_TO, "yyyy-MM-dd") remainingDays = remainingTimeUnit(currentDateTime, parsedDateTime, "days") if remainingDays > 30: return false else: return true
Working with numbers
If you need the output as number (for example if you use a math operator) the type
attribute needs to be added:
fieldProcessor: - field: numberField value: {{NumberField}} type: number - field: BudgetLeft value: {{sub BudgetPlanned BudgetLeft}} type: number
Format:
The expected number format is in locale en
. So "," for decimal comma and optional "." for thousand separator". If there is an issue in the number format or an empty string is given a fallback to decimal zero (0) is in place. When your output of the handlebar is not in this format consider to use "numberFormat" method before.
String | Decimal Value |
---|---|
1,000.00 | 1000.00 |
1000.00 | 1000.00 |
1 000.00 | 1000.00 |
NotANumber | 0.0 |
““ (blank string) | 0.0 |
Working with boolean
If you need the output as boolean the type
boolean attribute can be added:
fieldProcessor: - field: BudgetLeft value: '{{gt Amount 0}}' type: BOOLEAN
Here are some examples on the interpretation
TRUE
→true
true
→true
tRuE
→true
False
→false
notAValidValue
→false
(blank) →
false
Boolean Helper
In Helper
https://portrait.atlassian.net/wiki/spaces/PA7/pages/1029114243/Field+Processors#IN-Helper
Helper Functions
The following helper functions and their documentation are implemented and based on handlebars.java.
String Helpers
capitalizeFirst
Capitalizes the first character of the value.
{{capitalizeFirst value}}
If the value is “handlebars.java”, the output will be “Handlebars.java".
center
Centers the value in a field of a given width.
{{center value size=19 [pad="char"] }}
If the value is "Handlebars.java", the output will be " Handlebars.java "
cut
Removes all values of arg from the given string.
{{cut value [" "]}}
If the value is "String with spaces", the output will be "Stringwithspaces".
If you need to cut more characters, use it nested and without [ ]:
"{{ cut (cut P_LICENSE_M_LICENSETYPE_RELATION ')' ) '(' }}"
It truncates the “( )” from the GUID.
defaultIfEmpty
If value evaluates to False, uses the given default. Otherwise, uses the value.
{{defaultIfEmpty value "it is empty" }}
If the value is "" (the empty string), the output will be nothing.
join
Joins an array, iterator or an iterable with a string.
{{join value " // " [prefix=""] [suffix=""]}}
If the value is the list ['a', 'b', 'c'], the output will be the string "a // b // c".
ljust
Left-aligns the value in a field of a given width. Argument: field size
{{ljust value 20 [pad=" "] }}
If the value is Handlebars.java, the output will be "Handlebars.java “
rjust
Right-aligns the value in a field of a given width. Argument: field size
{{rjust value 20 [pad=" "] }}
If the value is Handlebars.java, the output will be " Handlebars.java".
substring
Returns a new CharSequence that is a subsequence of this sequence. The subsequence starts with the char value at the specified index and ends with the char value at index end - 1. Arguments: start offset, end offset.
{{substring value 11 }}
If the value is Handlebars.java, the output will be "java".
{{substring value 0 10 }}
If the value is Handlebars.java, the output will be "Handlebars".
{{substring value 5 9 }}
If the value is Handlebars.java, the output will be "bars".
lower
Converts a string into all lowercase.
{{lower value}}
If the value is 'Still MAD At Yoko', the output will be 'still mad at yoko'.
upper
Converts a string into all uppercase.
{{upper value}}
If the value is 'Hello', the output will be 'HELLO'.
slugify
Converts to lowercase, removes non-word characters (alphanumerics and underscores) and converts spaces to hyphens. Also strips leading and trailing whitespace.
{{slugify value}}
If the value is "Joel is a slug", the output will be "joel-is-a-slug".
stringFormat
Formats the variable according to the argument, a string formatting specifier.
{{stringFormat string param0 param1 ... paramN}}
If the value is "Hello %s" "handlebars.java", the output will be * "Hello handlebars.java".
stripTags
Strips all [X]HTML tags.
{{stripTags value}}
capitalize
Capitalizes all the whitespace separated words in a String.
{{ capitalize value [fully=false]}}
If the value is "my first post", the output will be "My First Post".
abbreviate
Truncates a string if it is longer than the specified number of characters. Truncated strings will end with a translatable ellipsis sequence ("..."). Argument: Number of characters to truncate to
{{abbreviate value 13 }}
If the value is "Handlebars rocks", the output will be "Handlebars...".
wordWrap
Wraps words at specified line length.
Argument: number of characters at which to wrap the text
{{ wordWrap value 5 }}
If value is Joel is a slug, the output would be:
Joel
is a
slug
replace
Replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence.
{{ replace value "..." "rocks" }}
If the value is "Handlebars ...", the output will be "Handlebars rocks".
yesNo
Maps values for true, false and (optionally) null, to the strings "yes", * "no", "maybe".
{{yesno value [yes="yes"] [no="no"] maybe=["maybe"] }}
dateFormat
The default date styles.
{{dateFormat date ["format"] [format="format"][tz=timeZone|timeZoneId]}}
Format parameters is one of:
"full": full date format. For example: Tuesday, June 19, 2012
"long": long date format. For example: June 19, 2012
"medium": medium date format. For example: Jun 19, 2012
"short": short date format. For example: 6/19/12
"pattern": a date pattern.
Otherwise, the default formatter will be used. The format option can be specified as a parameter or hash (a.k.a. named parameter).
numberFormat
Usage:
{{numberFormat number ["format"] [locale=default]}}
Format parameters is one of:
"integer": the integer number format
"percent": the percent number format
"currency": the decimal number format
"pattern": a decimal pattern.
Otherwise, the default formatter will be used.
More options:
groupingUsed: Set whether or not grouping will be used in this format.
maximumFractionDigits: Sets the maximum number of digits allowed in the fraction portion of a number.
maximumIntegerDigits: Sets the maximum number of digits allowed in the integer portion of a number
minimumFractionDigits: Sets the minimum number of digits allowed in the fraction portion of a number
minimumIntegerDigits: Sets the minimum number of digits allowed in the integer portion of a number.
parseIntegerOnly: Sets whether or not numbers should be parsed as integers only.
roundingMode: Sets the {@link java.math.RoundingMode} used in this NumberFormat.
toFloat
Formats a number value with fixed fractional digits:
{{toFloat PERCENTAGE_VALUE 4}}
now
Print the current date. Usage:
{{now ["format"] [tz=timeZone|timeZoneId]}}
Format parameters is one of:
"full": full date format. For example: Tuesday, June 19, 2012
"long": long date format. For example: June 19, 2012
"medium": medium date format. For example: Jun 19, 2012
"short": short date format. For example: 6/19/12
"pattern": a date pattern.
Otherwise, the default formatter will be used.
split
Use split functions to generate a list of a single string value.
{{splitByComma PARENT_IDS}}
Input: “1,2,3” Output: "[1,2,3]“ which will be added as an actual JSON array to the index. Useful for Organigram for example. saved JSON
"data": { "PARENT_IDS": "4,5", "PARENT_IDS_SPLIT": [ "4", "5" ],
Following operation are available
| regex: ";" |
| regex: "," |
| regex: "\n" |
| regex: " " |
| regex: "¶" |
Mathematics Operations
Use the following functions to apply basic mathematics operations.
If you need the results as number, you need to set the type accordingly!
See the chapter Working with numbers
Addition
Add values:
{{add value1 value2}}
If the value1 is 8
and value2 is 5
the output will be 13
.
Subtract
Subtract values:
{{sub value1 value2}}
If the value1 is 8
and value2 is 5
the output will be 3
.
Multiply
Multiply values:
{{mul value1 value2}}
If the value1 is 8
and value2 is 5
the output will be 40
.
Divide
Multiply values:
{{div value1 value2}}
If the value1 is 8
and value2 is 5
the output will be 1.6
.
Date Helpers
These Helpers handle DateTime
Objects. This means they always have an included time, in case nothing is provided 00:00:00.
parseDateTime
{{parseDateTime PORTRAIT_DATE "dd.MM.yyyy"}}
formatDateTime
{{formatDateTime PORTRAIT_DATE "dd.MM.yyyy"}}
currentDateTime
{{currentDateTime}}
remainingTimeUnit
{{remainingTimeUnit (currentDateTime) (parseDateTime P_LICENSE_M_VALID_TO "yyyy-MM-dd") "days"}}
The following Time units are supported:
seconds
minutes
hours
days
weeks
months
years
List Helper
In combination with split you can use simple loops to create more complex structures.
Details:
https://handlebarsjs.com/guide/builtin-helpers.html#each
Geo-Coding
addressToLatLng
Convert a human readable address into coordinates for showing the address on a map.
{{{addressToLatLng FULL_ADDRESS}}}
If the input is ‘Stephansplatz 1, 1010 Wien’, the output will be ‘48.208710, 16.372670’
Since the Map view expects the field Coordinates
, a full example would be:
sources: source: - id: 'MySource' fieldProcessor: - field: Coordinates value: '{{{addressToLatLng FULL_ADDRESS}}}'
Always use the 3-bracket style.
Geocoding must be configured in the application yaml and relies on a paid external service. See: Geocoding
Conditional Helpers
equals
Test if two elements are equals.
Render 'yes' or 'no':
{{#eq a b}} yes {{else}} no {{/eq}}
Render 'true' or 'false':
{{eq a b}}
Render 'y' or 'n':
{{eq a b yes='y' no='n'}}
not equals
Test if two elements are NOT equals.
Render 'yes' or 'no':
{{#neq a b}} yes {{else}} no {{/neq}}
Render 'true' or 'false':
{{neq a b}}
Render 'y' or 'n':
{{neq a b yes='y' no='n'}}
In
Check if a given value is contained in a given list of other values
{{in SELECT_VACATION_STATUS 'GENEHMIGT' 'ABGELEHNT'}}
Returns a boolean which can be chained
{{and (in SELECT_VACATION_STATUS 'GENEHMIGT' 'ABGELEHNT') (eq CURRENT_STATUS 'OFFEN')}}
Also a combination with various split methods is possible
{{in PORTRAIT_USER_EMAIL (splitBySemicolon EVENT_PARTICIPANTS) 'admin@portrait.com'}}
greater than
Greater operator (arguments must be comparable elements).
Render 'yes' or 'no':
{{#gt a b}} yes {{else}} no {{/gt}}
Render 'true' or 'false':
{gt a b}}
Render 'y' or 'n':
{{neq a b yes='y' no='n'}}
greater or equal
Greater or equal operator (arguments must be comparable) elements.
Render 'yes' or 'no':
{{#gte a b}} yes {{else}} no {{/gte}}
Render 'true' or 'false':
{{gte a b}}
Render 'y' or 'n':
{{gte a b yes='y' no='n'}}
less than
Less than operator (arguments must be comparable elements).
Render 'yes' or 'no':
{{#lt a b}} yes {{else}} no {{/lt}}
Render 'true' or 'false':
{{lt a b}}
Render 'y' or 'n':
{{lt a b yes='y' no='n'}}
less or equal
Less or equal operator (arguments must be {@link Comparable} elements.
Render 'yes' or 'no':
{{#lte a b}} yes {{else}} no {{/lte}}
Render 'true' or 'false':
{{lte a b}}
Render 'y' or 'n':
{{lte a b yes='y' no='n'}}
and
Truthiness of arguments is determined by isEmpty(Object), so this helper can be used with non-boolean values.
Render 'yes' or 'no'
{#and a b}} yes {{else}} no {{/and}}
Multiple arguments are supported too:
{{#and a b c d}} yes {{else}} no {{/and}}
Render 'true' or 'false':
{{and a b}}
Render 'y' or 'n':
{{and a b yes='y' no='n'}}
or
Truthiness of arguments is determined by isEmpty(Object), so this helper can be used with non-boolean values.
Render 'yes' or 'no':
{{#or a b}} yes {{else}} no {{/or}}
Multiple arguments are supported too:
{{#or a b c d}} yes {{else}} no {{/or}
Render 'true' or 'false':
{{or a b}
Render 'y' or 'n':
{{or a b yes='y' no='n'}}
not
Truthiness of arguments is determined by isEmpty(Object) so this helper can be used with non-boolean values.
Render 'yes' or 'no':
{{#not a}} yes {{else}} no {{/not}}
Render 'true' or 'false':
{{not a}}
Render 'y' or 'n':
{{not a yes='y' no='n'}}
Examples
The following examples are embedded in the config.yml annotation:
Call to Actions
If you want to provide a Call-To-Action, but the URI is not given in the source data, you can create your own:
Call
sources: source: - id: 'MySource' fieldProcessor: - field: ctaTel value: 'tel://{{tel}}'
{{tel}} is the telephone number from the source data in readable format
sources: source: - id: 'MySource' fieldProcessor: - field: ctaMail value: 'mailto://{{email}'
Source data contains the e-mail address in the field {{email}}}
URL’s (Google Maps)
sources: source: - id: 'MySource' fieldProcessor: - field: googleMapsCta value: 'https://maps.google.at?q={{address}}'
{{adress}} being the Address field from the source data
Replace empty values
sources: source: - id: 'MySource' fieldProcessor: - field: ResponsibilityCenter value: '{{defaultIfEmpty ResponsibilityCenter "Vienna" }}'
{{ResponsibilityCenter}} is sometimes empty in the source data. This field processor sets “Vienna”, in case the value would have been empty.
Build a Google Maps link based on meta data
The full address of your business partner is available in the source data in the field bp_address
(in case of ELO this is the internal group name of the index field = BP_ADDRESS
). You want to create a link that can later on used on the UI as an action-button:
sources: source: - id: 'MySource' fieldProcessor: - field: googleMapsCta value: 'https://maps.google.at?q={{bp_address}}'
Add a field
In this case we need a disclaimer inside Portrait which is not given in the source data. By defining a field name, which is not yet existing, the field disclaimer
will be added to each entry:
sources: source: - id: 'MySource' fieldProcessor: - field: disclaimer value: | Objects in the mirror are closer than they appear.
Excerpt - fieldProcessor can be used in a source.
Build a link inside a table
This example shows how to use a fieldProcessor inside an ELO mapping table. This configuration snippet will create a link to an external site, but will only be shown if the field MYAPP_REF_NR
is not empty:
maps: - domain: objekte name: MYAPP type: table fieldProcessor: - field: LINK_TO_WEBSHOP value: '{{#if MYAPP_REF_NR}}[Shop now](https://www.company.com/search?sSearch={{MYAPP_REF_NR}}){{/if}}'
Excerpt - fieldProcessor can be used in a elo map table.
Build a link for ELO Web Client
This example takes the unique key of Portrait (which is in fact the GUID for ELO sources) and embeds into an ELO web Client link:
sources: source: - id: 'MySource' fieldProcessor: - field: ctaWebClient value: 'http://eloserver:9090/web-Archive/#/archive/{{key}}/'
Build a link for ELO Java Client
This example takes the unique key of Portrait (which is in fact the GUID for ELO sources) and embeds into an ELO Java Client protocol handler link:
sources: source: - id: 'MySource' fieldProcessor: - field: ctaJavaClient value: 'elodms://({{key}})'
Remove brackets from GUID
In case your GUID is stored with leading trailing brackets, you can remove them with substring
.
Example inside a table:
maps: - domain: objekte name: MYAPP type: table fieldProcessor: - field: MYAPP_ELOGUID_WO_BRACKETS value: '{{substring MYAPP_ELOGUID 1 37 }}'
Shape for Orgchart view | Chained If-Else (aka. case or switch statement)
The Orgchart view supports a rounded shape. The shape should be rounded
, if the field CM_TYPE is has two specific values, otherwise use the default - which is rectangle
. This is a common issue in case of ELO Business Solutions. The same attribute can have two or more different values, due to the translated labels, which are part of the value. In the example the following logic should be realized:
Input | Output |
---|---|
M - Manager | rounded |
M - Vorgesetzter | rounded |
T - Teammitglied | rectangle |
S - Stellvertreter | rectangle |
sources: source: - id: 'MySource' fieldProcessor: - field: shape value: "{{#eq TYPE 'M - Manager'}}rounded{{ else }}{{#eq TYPE 'V - Vorgesetzter'}}rounded{{ else }}rectangular{{/eq}}{{/eq}}"
This example checks two values - you can extend this as you wish.
Colored Highlights
All views (List view, Orgchart view, Map view and Timeline view) support customizing the highlight color of the entries. Depending on the view different elements are colored. The field key is required to be highlight
the value as the hex code of the wanted color e.g. #ff0000
One way to achieve this is with a nested if else statement:
sources: source: - id: 'MySource' fieldProcessor: - field: highlight value: "{{#eq COUNTRY 'AUT'}}#ff0000{{ else }}{{#eq COUNTRY 'NLD'}}#4287f5{{ else }}#000000{{/eq}}{{/eq}}"