• Direct action

    By Nicolas GZA 2 decades ago

    I'm currently trying to implement Qenos WF.

    This is an amazing work! (congratulations)



    Nevertheless, I have been asked by some users to implement "submit" buttons instead of displaying a pop-up with different actions. How can I do that ?



    Related question : how to implement a submit button for a particular action in a view (ie for 1 or more documents to get to the next stage in a batch mode) ?



    Thanks.

    • Programmatically calling Actions using _QAF WF API

      By Mark Demicoli 2 decades ago

      Hi Nicolas!



      Use wfGetActionDoc() to retrieve the Action document you want to process then use wfProcessAction() to run it. You must save your document after calling wfProcessAction. In a view you can create an agent with a loop and cycle through selected documents.



      wfGetActionDoc (paramActionName As String, paramWFName As String, paramDB As notesDatabase, paramActionRef As String) As notesDocument



      PARAMS

      paramActionName - The name of the action you want to get

      paramWFName - the Workflow name in which the Action exists

      paramDB - the NotesDatabase in which they all live

      paramActionRef - optional reference number (a_Name) of the Action instead of paramActionName. This parameter takes precendence over paramActionName



      RETURN

      Returns the Action as a NotesDocument object.





      wfProcessAction (ActionDoc As notesDocument, paramDoc As notesDocument, optNotification As Integer, optIgnoreGlobalValidations) As Integer



      PARAMS

      ActionDoc - The Action you want to run as a NotesDocument object

      paramDoc - The context for the Action (ie the user document)

      optNotificaiton - set to True if you want Notifications sent from the Action

      optIgnoreGlobalValidations - set to True to ignore any Global validations specified by the Action's parent Workflow.



      RETURN

      Returns True if successful, false if it failed.



      USAGE

      This function processes a given QAF Action. Ie. The Action is processed in the same way as though it was selected by a user from the user interface (Action & Close / Create/ Admin Tools buttons), with the exception that the user document is not saved (you must do this), and window is not closed. This function can be called by server code only if the Action does not declare or use any UI classes in any called code.

      • Thanks

        By Nicolas GZA 2 decades ago

        Thanks Mark, it works perfect !



        Going deeper and deeper in the QAF features, I am more and more impressed by your work !



        I do not know where I could contribute but - for a start - I could translate QAF in french if you're interested, or more generally, I could help you to get a multilingual interface (I don't think the designer needs it, but the user interface [prompt messages…] do)



        2 other questions (and I may be rewarded chief designer!):


        • How could I get rid of messages like "notesuidocument : save cancelled" when a user cancels his/her modifications ?


        • If - in a view -I want a sort/categorization by status according to the process steps, should I name my statuses like "1. draft"… or could I use a config field (that I must have missed) in the "status" configuration doc ?
        • various

          By Mark Demicoli 2 decades ago

          Would love to have you on board Nicolas. Every good project needs French involvement!



          Down to business..

          You can already modify all the messages into any language by editing Custom WF Strings library and recompiling all the QAF libraries. When you do this can you send me a copy of it please?



          re: NotesUISavecancelled - can you give an example?

          re: Status sorting. You can use numbers in the State Alias field. In user documents, this value appears as a_Alias. You can then sort columns based on this field.

      • How to show/hide custom action buttons

        By Kevin Pettitt 2 decades ago

        Obviously when you're coding custom actions that use the wfProcessAction scripts you'll want to only show those actions when appropriate. Equally obvious is the fact you could handle this by hard-coding the hide-whens for the buttons to match the logic already contained in the QAF Action document.



        My question is whether there is already an elegant method available for keeping that dynamic linkage between action visibility and the underlying Action document?

        • Public Function wfGetUserActions

          By Mark Demicoli 2 decades ago

          _QAF WF API script library



          Public Function wfGetUserActions (paramDoc As NotesDocument, listAllActionsOnly As Integer) As Variant



          parameters:

          • paramDoc - notesDocument object which is the context used to determine list of valid actions
          • listAllActionsOnly (true/ false) - set to False for normal functioning. set to True if you want to just get a list of all Actions for the related workflow.
          • global constant MODE - set MODE to one of the following global constants before calling the function depending on which standard Action entry point you want to retrieve a list of actions for:



            MODE_ACTIONANDCLOSE

            MODE_CREATE

            MODE_ADMINTOOLS





            Return value:

            Array of strings

            Each element contains the Action name and reference number separated by pipe delimiter ( | )



            Usage for custom Action interfaces:

            The validity of actions can vary based on document fields and form mode (relevant Condition documents can have options ticked which hide/show the action based on whether the form is being edited or the document is new). The effective QAF Roles of the current user can also change on this basis. Therefore you may need to update the list of actions at some trigger point. If there is a field value dependancy, use the onChange or Exiting event of that field to perform an update. If the field dependancy is on a keyword field, you can trigger a form refresh when the keyword changes and update the list of actions in QueryModeChange.



            To process an action use:



            Public function wfProcessAction (ActionDocOrActionAlias As Variant, paramDoc As notesDocument, optNotification As Boolean, optIgnoreGlobalValidations As Boolean) As Boolean



            To get the Action document use:



            Public Function wfGetComponentByRef (RefNo as string, optForceViewRefresh As Boolean) As notesDocument





            … while writing this I realised there needs to be a MODE_ALL to retrieve all actions regardless of the entry point. Have just patched QAF WF API as follows:



            To Declarations add:



            Public Const MODE_ALL = "7"



            Replace lines 56-60 of the function wfGetUserActions with the following:



            If (aDoc.a_HideOption1(0) = "1" And paramDoc.StatusRef(0) = aDoc.a_NextStateRefNo(0))
            'If the Next Status is actually the current Status, then this Action is obviously (?!) not applicable
            Or (aDoc.a_HideOption3(0) = &quot;1&quot; And isLocal) _<br/>
            Or (aDoc.a_HideOption2(0) = &quot;1&quot;) _<br/>
            Or (Not aDoc.a_ActionButton(0) = MODE And (Not MODE = MODE_ALL)) _<br/>
            Then Goto SkipAction 
            
        • Public Function wfGetUserActions

          By Mark Demicoli 2 decades ago

          _QAF WF API script library



          Public Function wfGetUserActions (paramDoc As NotesDocument, listAllActionsOnly As Integer) As Variant



          parameters:

          • paramDoc - notesDocument object which is the context used to determine list of valid actions
          • listAllActionsOnly (true/ false) - set to False for normal functioning. set to True if you want to just get a list of all Actions for the related workflow.
          • global constant MODE - set MODE to one of the following global constants before calling the function depending on which standard Action entry point you want to retrieve a list of actions for:



            MODE_ACTIONANDCLOSE

            MODE_CREATE

            MODE_ADMINTOOLS



            Usage for alternative Action interfaces:

            The validity of actions can vary based on document fields and form mode (relevant Condition documents can have options ticked which hide/show the action based on whether the form is being edited or the document is new). The effective QAF Roles of the current user can also change on this basis. Therefore you may need to update the list of actions at some trigger point. If there is a field value dependancy, use the onChange or Exiting event of that field to perform an update. If the field dependancy is on a keyword field, you can trigger a form refresh when the keyword changes and update the list of actions in QueryModeChange.





            … while writing this I realised there needs to be a MODE_ALL to retrieve all actions regardless of the entry point. Have just patched QAF WF API as follows:



            To Declarations add:



            Public Const MODE_ALL = "7"



            Replace lines 56-60 of the function wfGetUserActions with the following:



            If (aDoc.a_HideOption1(0) = "1" And paramDoc.StatusRef(0) = aDoc.a_NextStateRefNo(0))
            'If the Next Status is actually the current Status, then this Action is obviously (?!) not applicable
            Or (aDoc.a_HideOption3(0) = &quot;1&quot; And isLocal) _<br/>
            Or (aDoc.a_HideOption2(0) = &quot;1&quot;) _<br/>
            Or (Not aDoc.a_ActionButton(0) = MODE And (Not MODE = MODE_ALL)) _<br/>
            Then Goto SkipAction 
            
          • Don't think I was clear about alternate action objective

            By Kevin Pettitt 2 decades ago

            Hi Mark,



            I may be missing something in your response but what I'm trying to do is have individual action buttons on the form (not the standard multiple choice dialog), and show/hide those actions as appropriate. At the moment, I have hide/when logic in the buttons themselves that duplicates what I've put into Condition documents, thus defeating the purpose of the Condition docs. I'd like to retain a linkage back to the condition doc, which I'm sure I could do through some sort of @Dblookup/@Eval approach, but I just wanted to check with you to see if there is already an established method of achieving this. If not, I guess I'll have to change that ;-).

            • inline form actions

              By Mark Demicoli 2 decades ago

              Sorry Kevin I guess I only insinuated a solution :) I've been thinking about this lately actually. There is not an elegant solution as yet but have been thinking about providing one.



              I think this could be done as follows:

              1. use wfGetUserActions() to retrieve list of valid actions based on current document, at some trigger point (eg queryModeChange, if you want the actions to be available in edit mode only, or querydocumentopen if you want the actions to be available all the time).
              2. Dynamic list of clickable actions displayed on the form (not sure how we would do this short of having a certain number of generic buttons or hotspots with hide-whens - not elegant). grr@lack of programmability in Notes - hope you're listening Bob :)
              3. When user clicks an action, wfGetuserActions() is used again to confirm that the action is still valid (ie fields may have changed causing conditions to return false). If so display message to that effect.



                brainstorm:
              4. wfGetUserActions is kinda slow at the moment - could be made more efficient to reduce delays.

                * could re-evaluate actions on query-recalc to make sure only valid actions are dispalyed. Recalc would have to be triggered when any editable fields that are tied to conditions that are tied to actions change
              • Proposed Solution for handling custom actions

                By Kevin Pettitt 2 decades ago

                Mark,



                Here's what I think would work:


                • Add a field to the "CustomStdActions" or "QenosWF" subforms called something like "QAFUserActionList" and have it populate on queryopen (?) based on the wfGetUserActions function.
                • Provide developer/user instructions on how to code hide-when formulas for custom actions, where a typical formula would be something like:



                  !UserActionList = "ActionAlias"



                  where "ActionAlias" is the same as that referenced in the action code itself using the "wfProcessAction" function.



                  Potential gotchas include how to deal with the fact that you're "changing" the document on the fly just to drive hide-whens…might be more prudent to throw the action list into a user profile doc and drive the hide when off of that - or even an environment variable that you cleanup/remove on the queryclose.



                  Alternatively, I actually have developed another clever profile doc technique where you use the queryopen to populate a
                  database profile doc with various values based on whatever code you write, but then you don't save* that profile. Despite not having been saved, those values are available to field formulas on the same form/subform via @GetProfileField. In this scenario the "QAFUserActionList" field would be computed for display and thus avoid issues of writing to the document unnecessarily.



                  I use this in SuperNTF in the "SYSTEM - View Action Header" form