11 | | The Assistant uses expressions to define what fields are presented to the user in different circumstances. For example, take the rules: |
| 11 | === Hiding a field |
| 12 | |
| 13 | The Assistant uses simple C-like expressions to define what fields are presented to the user in different circumstances. For example, let's assume that the tickets contain a fields named 'approval', that should be hidden if the ticket is in the 'new' or 'closed' state. Write a `kis_assistant` rule for `approval.visible`: |
| 14 | {{{#!ini |
| 15 | [kis_assistant] |
| 16 | approval.visible = !(status == 'new' || status == 'closed') |
| 17 | }}} |
| 18 | The expression syntax is similar to that of C or Javascript. An acceptable alternative would be: |
| 19 | {{{#!ini |
| 20 | [kis_assistant] |
| 21 | approval.visible = status != 'new' && status != 'closed' |
| 22 | }}} |
| 23 | Because lists of states are quite common however, the Assistant also provides an `in` operator, with very high precedence. So another acceptable alternative would be: |
21 | | This requires that a custom field named 'approval' is defined (either a Select or a Radio field) with options 'Not assessed', 'Denied' and 'Approved'. The first rule states that the field only appears when the ticket status is other than 'new' or 'closed'. The basic set of options 'Not assessed' or 'Denied' are always available, but the full set of options including 'Approved' is only available if the user is a member of the 'approver' group or if the field already had the value 'Approved' when the page was loaded. |
| 29 | In expressions, 'authname' evaluates to the authenticated name of the user, and 'status' evaluates to the current ticket status. |
| 30 | |
| 31 | === Hiding options |
| 32 | |
| 33 | Let's assume that we have a set of people on our project with the role of 'approver' (i.e. they are members of the Trac permissions group 'approver'). Let's also assume that the 'approval' field mentioned above is a Select or Radio field that has options 'Not assessed', 'Denied' and 'Approved'. The basic set of options 'Not assessed' or 'Denied' are available to all, but the full set of options including 'Approved' is only available if the user is a member of the 'approver' group or if the field already had the value 'Approved' when the page was loaded. |
| 34 | {{{#!ini |
| 35 | approval.options.basic_set = 'Not assessed', 'Denied' |
| 36 | approval.available.basic_set = true |
| 37 | approval.options.full_set = 'Approved' |
| 38 | approval.available.full_set = has_role('approver') || _approval == 'Approved' |
| 39 | }}} |
| 40 | The condition for the basic set of options being available is therefore just 'true'. The full set of options is available if the function 'has_role' returned 'true' when called with the parameter 'approver', or if the value of 'approval' when the page was loaded was already set to 'Approved'. The underscore in front of 'approval' means "use the value of this field at the time the page was loaded". |
| 41 | |
| 42 | === Using templates |
| 43 | |
| 44 | TBD |
| 45 | |
| 46 | === Updating the contents of fields automatically |
| 47 | |
| 48 | TBD |
| 49 | |
| 50 | === Blocking commits |
30 | | The first rule means that the ticket cannot be closed if the 'approval' field has not been set to the value 'Approved'. The second rule means that only a user who is a member of the group 'approver' can change the 'approval' field to that value. |
| 59 | The commit is blocked if any rule evaluates true. Therefore, the first rule means that the ticket cannot be closed if the 'approval' field has not been set to the value 'Approved'. The second rule means that only a user who is a member of the permissions group 'approver' can change the 'approval' field to that value. |
| 60 | |
| 61 | == Functions |
| 62 | |
| 63 | The 'has_role(<group>)' function is built-in, and returns true if and only if the user is a member of the named group. (A second parameter can be given, and allows a different user to be named, but this isn't normally needed.) |
| 64 | |
| 65 | Another built-in function is 'is_parent()', which returns true if and only if some other ticket has a field named 'parent' which contains a TracLink that points at the current ticket. It's designed to work with the TracChildTickets plugin. |
| 66 | |
| 67 | === User-defined functions |
| 68 | |
| 69 | User functions can be defined by adding a Python file to the Trac plugins folder that implements the `IConfigFunction` interface. For example: |
| 70 | {{{ |
| 71 | from trac.core import * |
| 72 | from kis import IConfigFunction |
| 73 | |
| 74 | class MyConfigFunctions(Component): |
| 75 | ''' Local functions for use by 'kisplugin' configuration files. |
| 76 | ''' |
| 77 | implements(IConfigFunction) |
| 78 | |
| 79 | # Example: implement named string constants |
| 80 | def safety(self, req, safety_enum): |
| 81 | if safety_enum == 'YES': |
| 82 | return 'Safety related' |
| 83 | if safety_enum == 'OK': |
| 84 | return 'Safety related - OK to close' |
| 85 | if safety_enum == 'NO': |
| 86 | return 'Not safety related' |
| 87 | }}} |
| 88 | This example would define a function 'safety()', implementing named constants. 'safety('OK')' returns the string 'Safety related - OK to close'. |
| 89 | The 'req' parameter is the HTTP request object; the remaining parameters are the parameters of the function call passed in from the configuration file. |
| 90 | |
| 91 | == What's new in version 2 |
| 92 | |
| 93 | * Function calls and user-defined functions. |
| 94 | * Automatic updating of fields. |
| 95 | * The operator 'has_role' has been retired and replaced with the 'has_role()' function. |
| 96 | * Labels and templates now have to be string expressions (in other words, they now need to be surrounded by single-quotes). |
| 97 | * New operators: arithmetic and comparison operators, and the ternary operator <expression> '?' <true_expression> ':' <false_expression> |
| 98 | * Changes to operator precedence: now very similar to that of Javascript. |