Changes between Version 3 and Version 4 of KeepInterfaceSimplePlugin


Ignore:
Timestamp:
Nov 24, 2016, 7:29:01 PM (7 years ago)
Author:
Jon Ashley
Comment:

Begin to document upcoming changes for version 2.0 of this plugin

Legend:

Unmodified
Added
Removed
Modified
  • KeepInterfaceSimplePlugin

    v3 v4  
    55== Description
    66
    7 This plugin supports complex workflows that contain lots of fields or have lots of rules about what is and isn't permitted. It can dynamically control what fields appear in the user interface depending on complex conditions that are nonetheless easy to define and configure. It can also block commits if necessary, such as when certain information hasn't been provided.
     7This plugin helps manage configurations that contain lots of fields or have lots of rules about what is and isn't permitted. It can dynamically control what fields appear in the user interface depending on easily-configurable conditions. It can also block commits if necessary, such as when certain information hasn't been provided.
    88
    9 There are two main components, named 'assistant' and 'warden'.
     9There are two main components, named 'assistant' and 'warden'. The Assistant manages the user-interface side, hiding and showing fields and options, and filling in fields for the user. The Warden enforces the rules that prevent commits.
    1010
    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
     13The 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]
     16approval.visible = !(status == 'new' || status == 'closed')
     17}}}
     18The expression syntax is similar to that of C or Javascript. An acceptable alternative would be:
     19{{{#!ini
     20[kis_assistant]
     21approval.visible = status != 'new' && status != 'closed'
     22}}}
     23Because lists of states are quite common however, the Assistant also provides an `in` operator, with very high precedence. So another acceptable alternative would be:
    1224{{{#!ini
    1325[kis_assistant]
    1426approval.visible = !status in 'new', 'closed'
    15 approval.options.basic_set = Not assessed, Denied
    16 approval.available.basic_set = true
    17 approval.options.full_set = Approved
    18 approval.available.full_set = authname has_role 'approver' || _approval == 'Approved'
    1927}}}
    2028
    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.
     29In expressions, 'authname' evaluates to the authenticated name of the user, and 'status' evaluates to the current ticket status.
     30
     31=== Hiding options
     32
     33Let'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
     35approval.options.basic_set = 'Not assessed', 'Denied'
     36approval.available.basic_set = true
     37approval.options.full_set = 'Approved'
     38approval.available.full_set = has_role('approver') || _approval == 'Approved'
     39}}}
     40The 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
     44TBD
     45
     46=== Updating the contents of fields automatically
     47
     48TBD
     49
     50=== Blocking commits
    2251
    2352The Warden prevents commits from being made if certain conditions aren't met. For example, take the rules:
     
    2554[kis_warden]
    2655approval required to close = status == 'closed' && approval != 'Approved'
    27 only designated approver can approve = !authname has_role 'approver' && approval != _approval && approval == 'Approved'
     56only designated approver can approve = !has_role('approver') && approval != _approval && approval == 'Approved'
    2857}}}
    2958
    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.
     59The 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
     63The '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
     65Another 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
     69User functions can be defined by adding a Python file to the Trac plugins folder that implements the `IConfigFunction` interface. For example:
     70{{{
     71from trac.core import *
     72from kis import IConfigFunction
     73
     74class 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}}}
     88This example would define a function 'safety()', implementing named constants. 'safety('OK')' returns the string 'Safety related - OK to close'.
     89The '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.
    3199
    32100== !Bugs/Feature Requests