Parfois, lors du développement d’un flux de travail, les outils dont nous avons discuté jusqu’à présent ne suffiront pas à mettre en œuvre la logique requise. En règle générale, cela se produit chaque fois que vous devez manipuler les données d’entrée brutes, par exemple avant de les comparer dans une expression ou avant de les enregistrer dans une variable de contexte. Dans ces cas, l’option d’utiliser notre moteur JavaScript (JS) intégré dans le balisage du flux de travail devrait offrir une solution viable.

Toute utilisation de JavaScript dans un flux de travail doit toujours se faire à l’intérieur d’une <![CDATA[ ... ]]> balise pour éviter les erreurs d’analyseur XML. Une portée JS est ouverte et fermée à l’aide de ?{ ... }?. Vous pouvez accéder aux variables de contexte à partir de l’étendue JS à l’aide de context.variable_name. Pour accéder aux données d’événement, vous utiliserez de la même manière, event.fieldpar exemple :

<setvar id="add_digit_from_speech_command">
    <context_of>workflow</context_of>
    <context_update>
        <param name="number » type="long">< ![ CDATA[ ?{ context.number + Number(event.command.substr(event.command.length - 1, event.command.length)) } ? ]] ></param>
    </context_update>
</setvar>

Comme vous pouvez le voir dans l’exemple ci-dessus, vous pouvez écrire du JS natif arbitraire. Cela peut également s’étendre sur plusieurs lignes et à des manipulations plus complexes. Vous verrez d’autres exemples dans le prochain article.

Fonctions intégrées

Il existe quelques fonctions intégrées que vous pouvez utiliser directement dans le XML du flux de travail sans ouvrir de contexte JS. Certains de ces exemples sont régulièrement utilisés dans des cas d’utilisation spécifiques :

  • exists : exists(#{shelve})
  • toUppercase : toUppercase( '#{material_name}' )
  • toLowercase : toLowercase( '#{material_name}')
  • trim : trim( #{material_name} )
  • contient : contient( #{first_code}, #{second_code})
  • startsWith : startsWith( #{first_code}, #{second_code})
  • endsWith : endsWith( #{first_code}, #{second_code})
  • égal à : égal à ( #{first_code}, #{second_code})
  • sous-chaîne : sous-chaîne( #{material_name}, 0, 3)

L’exemple ci-dessous contient les fonctions , trim,et substring .toUpperCase

<rule id="speak_material">
    <expression>< ![ CDATA[ #{event :command} == toUpperCase('#{material_name}') ]]></expression>
    <actions>
        <setvar id="set_material_type">
            <context_update>
                <param name="material_type » type="string">trim(substring(#{material_name}, 0, 3))</param>
            </context_update>
        <setvar>
    </actions>
</rule>

Ce qui précède est un exemple typique, car les commandes vocales sont toujours émises en majuscules. Si vous souhaitez comparer une commande vocale à un contenu de votre flux de travail, vous devez toujours la transformer en majuscules.

Trucs et astuces : N’utilisez pas d’espace blanc pour une meilleure lisibilité du code dans une param balise de type string, car elle ferait partie de la chaîne que vous manipulez. Par exemple, <param name="material_type" type="string">trim(substring(#{material_name}, 0, 3)) </param> cela donnerait par exemple MAT_ (où _ est un espace blanc) même si vous avez utilisé trim.

Exemple

Examinons quelques autres exemples de cas d’utilisation où le moteur JS est utile :

Accès dynamique aux données

Parfois, vous avez besoin d’accéder aux données de manière dynamique (en fonction du contenu d’une autre variable de contexte) :

    <setvar id="set_step">
        <context_update>
            <param name="step » type="objet">< ![ CDATA[ ?{ context.steps[context.current_step_index]} ? ]]></param>
        </context_update>
    </setvar>

Manipulation conditionnelle des données

Bien que vous puissiez également créer plusieurs actions et règles pour implémenter cela, JS permet la brièveté :

    <setvar id="set_text_color">
        <context_update>
            <param name="label_text_color » type="string">< ![ CDATA[ ?{ (contexte.urgent) ? 'rouge' : 'noir' } ? ]]></param>
        </context_update>
    </setvar>

Génération et manipulation d’objets

JavaScript vous aide également à générer ou à manipuler des objets. Dans l’exemple ci-dessous, nous voulons permettre au worker d’utiliser des commandes vocales pour exprimer une quantité comprise entre 0 et 99. Chaque commande vocale doit être ajoutée à la grammaire vocale séparément, mais en utilisant JavaScript, nous pouvons raccourcir cela à :

<action id="add_amount_speech_commands » type="speech_modify_commands_in_grammar">
    <param name="slot">wf_editor_slot</param>
    <param name="commandes">< ![ CDATA[ ?{
        Array.apply(null, {length : 100})
             .map(Number.call, Number)
             .map(function(e) { 
                    return { 'name' : 'AMOUNT ' + (e), 'description' : 'AMOUNT [0-99]'}
                }
        )} ? ]] ></param>
    <param name="modification">add_commands</param>
</action>

Dans les expressions

Il existe également des cas d’utilisation où JS aide dans les expressions. Dans l’exemple ci-dessous, nous traitons un événement qui est émis lorsqu’un appareil tiers est déconnecté. Nous utilisons JS pour rechercher dans une chaîne d’adresses MAC l’adresse MAC de l’appareil déconnecté.

<rule id="device_vanished">
    <expression>< ![ CDATA[ #{event :command}== 'DEVICEVANISHED' && ?{ context.mac.search(event.mac)>-1} ?]] ></expression>
    <actions>
        <action ref="back_to_start"/>
    </actions>
</rule>

Remarque : L’utilisation de JavaScript est limitée pour les expressions. Le contenu de toutes les expressions sera coupé pour supprimer tous les sauts de ligne et les espaces qui pourraient rompre la logique. Par conséquent, vous ne pouvez pas utiliser plusieurs lignes de JavaScript dans les expressions.

Widget générique

Un autre cas d’utilisation typique de JS est le widget générique. Comme nous n’avons pas encore introduit la mise en page, nous n’examinerons pas d’exemple ici, mais la documentation du widget en a un.

📌Mission

Dans la version actuelle de notre composant, la sortie de notre choix est entièrement en majuscules et est affichée comme telle dans l’interface utilisateur du composant suivant. Rendons-le un peu plus joli :

  • Utilisez JavaScript ou des fonctions intégrées pour enregistrer le choix résultant dans une majuscule plus naturelle.

 Télécharger le composant (pré-affectation)

Solution

Vous trouverez ci-dessous une solution exemplaire :

<rule id="choice_made">
    <expression>< ![ CDATA[ #{event :command} == 'POMME' || #{événement :commande} == 'PEAR' ]]></expression>
    <actions>
        <setvar id="save_choice">
            <context_of>workflow</context_of>
            <context_update>
                <param name="choice » type="string">< ![ CDATA[ ?{ event.command.slice(0,1) + event.command.slice(1).toLowerCase() } ? ]] ></param>
            </context_update>
        </setvar>
        <action ref="show_confirmation_dialog"/>
    </actions>
</rule>  

 Télécharger le composant (post-affectation)

Dans la prochaine leçon, nous verrons enfin comment concevoir l’interface utilisateur d’un composant.