ilscipio/scipio-erp

View on GitHub
framework/webtools/widget/MiscScreens.xml

Summary

Maintainability
Test Coverage
<!--
This file is subject to the terms and conditions defined in the
files 'LICENSE' and 'NOTICE', which are part of this source
code package.
-->

<screens xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/widget-screen.xsd">

    <!-- SCIPIO: include-screens test -->
    <include-screens location="component://webtools/widget/MiscExtraScreens.xml"/>

    <screen name="viewdatafile">
        <section>
            <actions>
                <set field="titleProperty" value="WebtoolsDataFileMainTitle"/>
                <set field="activeSubMenuItem" value="data"/>
                <script location="component://webtools/webapp/webtools/WEB-INF/actions/datafile/viewdatafile.groovy"/>
            </actions>
            <widgets>
                <decorator-screen name="CommonImportExportDecorator" location="${parameters.mainDecoratorLocation}">
                    <decorator-section name="body">
                        <screenlet>
                            <platform-specific><html><html-template location="component://webtools/webapp/webtools/datafile/viewdatafile.ftl"/></html></platform-specific>
                        </screenlet>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>

    <screen name="WebtoolsLayoutDemoActions">
        <actions>
            <set field="debugMode" from-field="parameters.debugMode" type="Boolean" default-value="false" />
            <set field="allowErrors" from-field="parameters.allowErrors" type="Boolean" default-value="false" />
            <if>
                <condition><if-true field="parameters.debugMode"/></condition><!-- NOTE: if-true succeeds with either proper Boolean or string of boolean, "true" -->
                <then>
                    <script lang="groovy"><![CDATA[
                        import org.ofbiz.base.util.*;
                        
                        Debug.logInfo("\n\n"
                            + "******************************************************\n"
                            + "Running layout demo in Debug mode\n"
                            + "******************************************************\n"
                            + "Note: This screen intentionally causes some log warnings and errors for testing purposes.\n"
                            + "See component://webtools/widget/MiscScreens.xml#WebtoolsLayoutDemo and related resources for details.\n"
                            + "URL: " + request.getRequestURL() + (request.getQueryString() ? "?" + request.getQueryString() : "") + "\n"
                            , "LayoutDemoActions.groovy");
                        
                        Debug.logInfo("Testing GeneralException messages...", "LayoutDemoActions.groovy");
                        try {
                            throw new GeneralException();
                        } catch(GeneralException e) {
                            Debug.logInfo("GeneralException getMessage(): " + e.getMessage(), "LayoutDemoActions.groovy");
                        }
                        try {
                            throw new GeneralException("Main exception detail message");
                        } catch(GeneralException e) {
                            Debug.logInfo("GeneralException getMessage(): " + e.getMessage(), "LayoutDemoActions.groovy");
                        }
                        try {
                            throw new GeneralException("Main exception detail message").setPropertyMessage(PropertyMessage.makeFromStatic("Main exception detail property message"));
                        } catch(GeneralException e) {
                            Debug.logInfo("GeneralException getMessage(): " + e.getMessage(), "LayoutDemoActions.groovy");
                        }
                        try {
                            throw new GeneralException(new IllegalArgumentException("a nested exception")).setPropertyMessage(PropertyMessage.makeFromStatic("Main exception detail property message"));
                        } catch(GeneralException e) {
                            Debug.logInfo("GeneralException getMessage(): " + e.getMessage(), "LayoutDemoActions.groovy");
                        }
                        try {
                            msgs = [];
                            msgs.add(PropertyMessage.make("WebtoolsUiLabels", "WebtoolsTestLabel"));
                            msgs.add("Static string message 1, non-localized");
                            msgs.add(PropertyMessage.make("WebtoolsUiLabels", "WebtoolsTestLabel_en"));
                            msgs.add("Static string message 2, non-localized");
                            msgs.add(PropertyMessage.make("WebtoolsUiLabels", "WebtoolsTestLabel_de"));
                            throw new GeneralException("Main exception detail message", msgs).setPropertyMessage(PropertyMessage.makeFromStatic("Main exception detail property message"));
                        } catch(GeneralException e) {
                            Debug.logInfo("GeneralException getMessage(): " + e.getMessage(), "LayoutDemoActions.groovy");
                            Debug.logInfo("GeneralException messages (default prop locale): " + e.getMessageList().toString(), "LayoutDemoActions.groovy");
                            Debug.logInfo("GeneralException messages (default log locale): " + PropertyMessage.getLogMessages(e.getPropertyMessageList()).toString(), "LayoutDemoActions.groovy");
                            Debug.logInfo("GeneralException messages (german): " + e.getMessageList(Locale.GERMAN).toString(), "LayoutDemoActions.groovy");
                            Debug.logInfo("GeneralException messages (german 2): " + PropertyMessage.getMessages(e.getPropertyMessageList(), Locale.GERMAN).toString(), "LayoutDemoActions.groovy");
                        }
                        try {
                            msgs = [];
                            msgs.add(PropertyMessage.make("WebtoolsUiLabels", "WebtoolsTestLabel"));
                            msgs.add("Static string message 1, non-localized");
                            msgs.add(PropertyMessage.make("WebtoolsUiLabels", "WebtoolsTestLabel_en"));
                            msgs.add("Static string message 2, non-localized");
                            msgs.add(PropertyMessage.make("WebtoolsUiLabels", "WebtoolsTestLabel_de"));
                            throw new GeneralException("Main exception detail message", msgs, new IllegalArgumentException("a nested exception"));
                        } catch(GeneralException e) {
                            Debug.logInfo("GeneralException getMessage(): " + e.getMessage(), "LayoutDemoActions.groovy");
                            Debug.logInfo("GeneralException messages (default prop locale): " + e.getMessageList().toString(), "LayoutDemoActions.groovy");
                            Debug.logInfo("GeneralException messages (default log locale): " + PropertyMessage.getLogMessages(e.getPropertyMessageList()).toString(), "LayoutDemoActions.groovy");
                            Debug.logInfo("GeneralException messages (german): " + e.getMessageList(Locale.GERMAN).toString(), "LayoutDemoActions.groovy");
                            Debug.logInfo("GeneralException messages (german 2): " + PropertyMessage.getMessages(e.getPropertyMessageList(), Locale.GERMAN).toString(), "LayoutDemoActions.groovy");
                        }
                    ]]></script>
                </then>
                <else>
                    <script lang="groovy"><![CDATA[
                        import org.ofbiz.base.util.Debug;
                        Debug.logInfo("Running layout demo in regular mode", "LayoutDemoActions.groovy");
                    ]]></script>
                </else>
            </if>
            <!-- SCIPIO: NEW: flexible locations for <script> location -->
            <set field="adminScriptsBaseDir" value="component://webtools/webapp/webtools/WEB-INF/actions" />
            <script location="${adminScriptsBaseDir}/misc/PrepareLayoutDemo.groovy"/>

            <include-screen-actions name="hotwireActions"/>
        </actions>
    </screen>

    <screen name="WebtoolsLayoutDemo">
        <!-- Demonstrates UI layout best practices and serves as a visual theme test jig.
        For more information:
        https://cwiki.apache.org/OFBADMIN/user-interface-layout-best-practices.html
        https://cwiki.apache.org/OFBADMIN/html-and-css-best-practices.html
        https://cwiki.apache.org/OFBIZ/ofbiz-maincsscss-html-element-collection-styles.html
        -->
        <section>
            <actions>
                <include-screen-actions name="WebtoolsLayoutDemoActions"/>
                <set field="testtest" value="test ' asdf ' &gt; asdf &lt; asdfasdf" />
                <property-map resource="WebtoolsUiLabels" map-name="uiLabelMap" global="true"/>
                <set field="titleProperty" value="WebtoolsLayoutDemo"/>
                <set field="activeSubMenu" from-field="activeSubMenu" default-value="LayoutDemo" />
                <set field="activeSubMenuItem" value="${groovy: (context.debugMode ? 'LayoutDemoDebug' : 'LayoutDemo')}"/>
                <set field="demoText" value="${uiLabelMap.WebtoolsLayoutDemoText}" global="true"/>
                <set field="errorMessage" from-field="demoText" global="true"/>
                <set field="eventMessage" from-field="demoText" global="true"/>
                <set field="demoTargetUrl" value="LayoutDemo"/>
                <set field="demoParam1" value="one"/>
                <set field="demoParam2" value="two"/>
                <set field="demoParam3" value="three"/>
                <set field="demoMap.name" value="${uiLabelMap.WebtoolsLayoutDemo}"/>
                <set field="demoMap.description" value="${uiLabelMap.WebtoolsLayoutDemoText}"/>
                <set field="demoMap.dropDown" value="Y"/>
                <set field="demoMap.checkBox" value="Y"/>
                <set field="demoMap.radioButton" value="Y"/>
                <set field="demoList[]" from-field="demoMap"/>
                <set field="demoList[]" from-field="demoMap"/>
                <set field="demoList[]" from-field="demoMap"/>
                <set field="altRowStyle" value=""/>
                <set field="headerStyle" value="header-row-1"/>
                <set field="tableStyle" value="${styles.table_data_list} light-grid"/>
                <set field="ofbizWidgetsLayoutScreenLocation" value="component://webtools/widget/MiscScreens.xml#WebtoolsLayoutDemoOfbizWidgets" />
                <set field="parameters.showLeftColumn" value="Y" />
                <set field="complexCharString" value="&amp; &lt; &gt; ' &quot; [] () ü ö ä Ä Ü Ö ß"/>
                <set field="demoScreenContentUri" value="/admin/images/does_not_exist.jpg?param1=value1&amp;param2=value2"/><!-- NOTE: the &amp; only bypasses this xml, not html -->
                <set field="contentPathPrefix" value="https://ilscipio.com/images"/>
                
                <script lang="groovy"><![CDATA[
                    import org.ofbiz.base.util.*;
                    import org.ofbiz.entity.condition.*;
                    import org.ofbiz.entity.util.*;
                    shopInfo = [:];
                    try {
                        def shopWebSite = EntityQuery.use(delegator).from("WebSite").where("webSiteId", "ScipioWebStore").cache().queryOne();
                        if (!shopWebSite) {
                            // FIXME: missing logic to find most-appropriate default website in this case
                            shopWebSite = EntityQuery.use(delegator).from("WebSite")
                                .where(EntityCondition.makeCondition("productStoreId", EntityOperator.NOT_EQUAL, null)).cache().queryFirst();
                        }
                        Debug.logInfo("Using website for shop tests: " + (shopWebSite ? shopWebSite.webSiteId : "[missing]"), "InlineDemoScript.groovy");
                        
                        if (shopWebSite) {
                            shopInfo.webSiteId = shopWebSite.webSiteId;
                            shopInfo.mountPoint = org.ofbiz.webapp.WebAppUtil.getWebappInfoFromWebsiteId(shopWebSite.webSiteId).getContextRoot();
                        }
                    } catch(Exception e) {
                        Debug.logError(e, "Cannot get WebSite for shop tests", "InlineDemoScript.groovy");
                    }
                    context.shopInfo = shopInfo;
                ]]></script>

                <!-- WebSockets example (NOTE: to enable, set webSocket=true in catalina.properties) -->
                <property-to-field resource="catalina" property="webSocket" field="webSocketEnabled"/>
                <set field="webSocketEnabled" type="Boolean" from-field="webSocketEnabled" default-value="false"/>
                <if>
                    <condition>
                        <and>
                            <if-true field="webSocketEnabled"/>
                            <if-has-permission permission="OFBTOOLS" action="_VIEW"/>
                        </and>
                    </condition>
                    <then>
                        <set field="layoutSettings.javaScripts[]" value="/webtools/images/ExamplePushNotifications.js" global="true"/>
                    </then>
                </if>
            </actions>
            <widgets>
                <decorator-screen name="CommonWebtoolsAppDecorator" location="${parameters.mainDecoratorLocation}">
                    <decorator-section name="body">
                        <section>
                            <condition>
                                <if-has-permission permission="OFBTOOLS" action="_VIEW"/>
                            </condition>
                            <widgets>
                                <section name="Grid">
                                    <widgets>
                                        <platform-specific><html><html-template location="component://webtools/webapp/webtools/layout/layoutdemo.ftl"/></html></platform-specific>
                                        <!-- let the FTL include this because it adds useful tests
                                        <horizontal-separator/>
                                        <label text="Widget tests" style="h" />
                                        <include-screen name="WebtoolsLayoutDemoOfbizWidgets" />-->
                                    </widgets>
                                </section>
                            </widgets>
                            <fail-widgets>
                                <label style="common-msg-error-perm">${uiLabelMap.WebtoolsViewPermissionError}</label>
                            </fail-widgets>
                        </section>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>

    <screen name="WebtoolsLayoutDemoOfbizWidgetActions">
        <actions><!-- NOTE: In an actions-only screen, should skip the top section and all else - only have actions element. -->
            <script lang="groovy"><![CDATA[
                globalContext.layoutDemoTestVar123 = "Test value 123";
                context.layoutDemoTestVar123 = "Test value 123";
                context.commonActionField5 = "This value 5 was set in a dynamically included script. [SUCCESS]";
            ]]></script>
            <include-screen-actions name="WebtoolsLayoutDemoExtraPoorActions"/>
        </actions>
    </screen>

    <screen name="WebtoolsLayoutDemoExtraPoorActions">
        <section><!-- NOTE: In a good actions-only screen def, you omit this top <section> and all <widgets/> sections... -->
            <actions>
                <!-- These are included by include-actions directive. -->
                <set field="commonActionField1" value="This value 1 was set in WebtoolsLayoutDemoExtraPoorActions screen actions included using the new include-actions screen widget directive. [SUCCESS]"/>
                <set field="commonActionField2" value="This value 2 was set in WebtoolsLayoutDemoExtraPoorActions screen actions included using the new include-actions screen widget directive, but should get overridden by another include. [ERROR]"/>
            </actions>
            <widgets>
                <section>
                    <actions>
                        <!-- These are NOT included by include-screen-actions directive. -->
                        <set field="nonCommonActionField4" value="This value 4 was set in WebtoolsLayoutDemoOfbizWidgetActions outside its top section and should not be included by include-actions. [ERROR]"/>
                    </actions>
                </section>
            </widgets>
        </section>
    </screen>

    <screen name="WebtoolsLayoutDemoOfbizWidgets">
        <section>
            <actions>
                <set field="clearFieldTest1" value="[This is a test of the clear-field directive]"/>
                <script lang="groovy">org.ofbiz.base.util.Debug.logInfo("clearFieldTest1 (pre-clear-field): " + context.clearFieldTest1, "InlineClearFieldTest.groovy");</script>
                <clear-field field="clearFieldTest1"/>
                <script lang="groovy">org.ofbiz.base.util.Debug.logInfo("clearFieldTest1 (post-clear-field, should be null): " + context.clearFieldTest1, "InlineClearFieldTest.groovy");</script>

                <set field="commonActionField1" value="This value should get overridden... [ERROR]"/>
                <set field="commonActionField2" value="This value should get overridden... [ERROR]"/>
                <set field="nonCommonActionField4" value="This value should keep its original value from WebtoolsLayoutDemoOfbizWidgets. [SUCCESS]"/>
                <set field="commonActionField5" value="This value should get overridden... [ERROR]"/>
                <!-- Scipio directive to easily reuse screen actions -->
                <include-screen-actions name="WebtoolsLayoutDemoOfbizWidgetActions"/>
                <!-- It's even possible to include actions from different widget types! -->
                <include-form-actions name="LayoutDemoActionsIncludeTest2" location="component://webtools/widget/MiscForms.xml"/>
                <!-- dynamic form -->
                <set field="miscMenusLocation" value="component://webtools/widget/MiscMenus.xml"/>
                <include-menu-actions name="WebtoolsMenuActionsDemo4" location="${miscMenusLocation}"/>
                
                <!-- Test for inline scripts (new in Scipio) and GroovyBaseScript extension for inline scripts (new in Scipio, 2017-01-27) -->
                <script lang="groovy"><![CDATA[
                    import org.ofbiz.base.util.*;
                    productStores = select("productStoreId").from("ProductStore").orderBy("productStoreId").cache(true).queryList().collect { it.productStoreId };
                    Debug.logInfo("Product stores in system (cached): " + productStores, "InlineDemoScript.groovy");
                ]]></script>
                <!-- NOTE: in the following, we cannot use the nice groovy collect() method with closure, because syntax doesn't support nested brackets... -->
                <set field="dummy" value="${groovy: import org.ofbiz.base.util.*; Debug.logInfo('WebSite records in system (cached): ' + UtilMisc.collectMapValuesForKey(from('WebSite').orderBy('webSiteId').cache(true).queryList(), 'webSiteId'), 'InlineDemoAssignScript.groovy'); '';}"/>

                <!-- simple-method test -->
                <script><![CDATA[groovy:
                    import org.ofbiz.base.util.*;
                    final module = "InlineDemoScript.groovy";
                    Debug.logInfo("--------------------------------------", module);
                    Debug.logInfo("bsh warnings/compat test", module);
                    Debug.logInfo("--------------------------------------", module);
                ]]></script>
                <script location="component://webtools/script/com/ilscipio/scipio/webtools/MiscSimpleMethods.xml#testBshCompat"/>
                <script lang="groovy"><![CDATA[
                    import org.ofbiz.base.util.*;
                    final module = "InlineDemoScript.groovy";
                    Debug.logInfo("Some messages returns from testSimpleMethods1: " + testSmOutVar1 + " " + testSmOutVar2, module);
                    Debug.logInfo("--------------------------------------", module);
                ]]></script>

                <if>
                    <condition>
                        <if-component component-name="webtools"/>
                    </condition>
                    <then>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logInfo("admin component exists", module);
                        ]]></script>
                    </then>
                    <else>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logError("admin component does not exist!", module);
                        ]]></script>
                    </else>
                </if>
                <if>
                    <condition>
                        <if-service service-name="superFakeComponent"/>
                    </condition>
                    <then>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logError("superFakeComponent component exists!", module);
                        ]]></script>
                    </then>
                    <else>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logInfo("superFakeComponent component does not exist", module);
                        ]]></script>
                    </else>
                </if>
                
                <if>
                    <condition>
                        <if-entity entity-name="WebSite"/>
                    </condition>
                    <then>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logInfo("WebSite entity exists", module);
                        ]]></script>
                    </then>
                    <else>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logError("WebSite entity does not exist!", module);
                        ]]></script>
                    </else>
                </if>
                <if>
                    <condition>
                        <if-entity entity-name="SuperFakeEntity"/>
                    </condition>
                    <then>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logError("SuperFakeEntity entity exists!", module);
                        ]]></script>
                    </then>
                    <else>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logInfo("SuperFakeEntity entity does not exist", module);
                        ]]></script>
                    </else>
                </if>
                <if>
                    <condition>
                        <if-service service-name="createProductStore"/>
                    </condition>
                    <then>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logInfo("createProductStore service exists", module);
                        ]]></script>
                    </then>
                    <else>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logError("createProductStore service does not exist!", module);
                        ]]></script>
                    </else>
                </if>
                <if>
                    <condition>
                        <if-service service-name="superFakeService"/>
                    </condition>
                    <then>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logError("superFakeService entity exists!", module);
                        ]]></script>
                    </then>
                    <else>
                        <script lang="groovy"><![CDATA[
                            import org.ofbiz.base.util.*;
                            final module = "InlineDemoScript.groovy";
                            Debug.logInfo("superFakeService entity does not exist", module);
                        ]]></script>
                    </else>
                </if>
            </actions>
            <widgets>
                <!-- 
                <section name="h1-h6 Styles">
                    <widgets>
                        <horizontal-separator/>
                        <label style="h1" text="H1."/>
                        <label style="heading" text="H2."/>
                        <label style="heading+1" text="H3."/>
                        <label style="heading+2" text="H4."/>
                        <label style="heading+3" text="H5."/>
                        <label style="heading+4" text="H6."/>
                    </widgets>
                </section>
                 
                <section name="Form/List Styles">
                    <widgets>
                        <horizontal-separator/>
                        <include-form name="LayoutDemoForm" location="component://webtools/widget/MiscForms.xml"/>                                        <section>
                            <actions>
                                <set field="tableStyle" value="${styles.table_data_list} dark-grid"/>
                            </actions>
                        </section>
                        <section>
                            <actions>
                                <set field="altRowStyle" value="alternate-row"/>
                                <set field="headerStyle" value="header-row-2"/>
                                <set field="tableStyle" value="${styles.table_data_list} hover-bar"/>
                            </actions>
                        </section>
                        <include-form name="LayoutDemoList" location="component://webtools/widget/MiscForms.xml"/>
                    </widgets>
                </section>
                <section name="Screenlet Styles">
                    <widgets>
                        <screenlet title="${uiLabelMap.WebtoolsLayoutDemo}" padded="false">
                            <section>
                                <actions>
                                    <set field="altRowStyle" value="alternate-row"/>
                                    <set field="headerStyle" value="header-row-2"/>
                                    <set field="tableStyle" value="${styles.table_data_list} hover-bar"/>
                                    <set field="viewSize" value="1" type="Integer"/>
                                </actions>
                            </section>
                            <include-form name="LayoutDemoList" location="component://webtools/widget/MiscForms.xml"/>
                        </screenlet>
                    </widgets>
                </section>
                -->
                <screenlet title="Widget language tests">
                    <screenlet title="include-actions directive">
                        <label text="commonActionField1 value: ${commonActionField1}"/>
                        <label text="commonActionField2 value: ${commonActionField2}"/>
                        <label text="commonActionField3 value: ${commonActionField3}"/>
                        <label text="nonCommonActionField4 value: ${nonCommonActionField4}"/>
                        <label text="commonActionField5 value: ${commonActionField5}"/>
                        <label text="commonActionField6 value: ${commonActionField6}"/>
                        <label text="commonActionField7 value: ${commonActionField7}"/>
                        <label text="commonActionField8 value: ${commonActionField8}"/>
                        <label text="commonActionField9 value: ${commonActionField9}"/>
                    </screenlet>
                </screenlet>
                <screenlet title="Screenlets" id="my-widget-screenlet-parent" navigation-menu-name="WebtoolsInlineSectionMenuDemo">
                    <include-menu location="component://webtools/widget/MiscMenus.xml" name="WebtoolsInlineSectionMenuDemo"/>
                    <label text="This section/screenlet has a special legacy Ofbiz navigation menu, rendered as section-inline menu type by default."/>
                    <screenlet id="my-widget-screenlet-child" title="Complex title style" title-style="container:mycontainerclass;h:mytitleclass"></screenlet>
                    <screenlet title="Complex title style 2 (override title elem)" title-style="container:mycontainerclass;container:+mytitleclass"></screenlet>
                    <screenlet title="Complex title style 3 (no classes)" title-style="container;span"></screenlet>
                </screenlet>
                <screenlet title="Heading labels">
                    <label style="container:mycontainerclass;heading:myheadingclass" text="Complex title style"/>
                    <label style="heading:myheadingclass" text="Complex title style 3"/>
                    <label style="div:mycontainerclass;h" text="Complex title style 4"/>
                    <label style="h1" text="H1."/>
                    <label style="h2" text="H2."/>
                    <label style="h3" text="H3."/>
                    <label style="h4" text="H4."/>
                    <label style="h5" text="H5."/>
                    <label style="h6" text="H6."/>
                    <label style="heading" text="Heading+0"/>
                    <label style="heading+1" text="Heading+1"/>
                    <label style="heading+2" text="Heading+2"/>
                    <label style="heading+3" text="Heading+3"/>
                    <label style="heading+4:myheadingclass" text="Heading+4 (replacing class)"/>
                    <label style="heading+4:+myheadingclass" text="Heading+4 (adding class)"/>
                </screenlet>
                <screenlet title="Specific markup labels">
                    <label style="generic" text="Generic markup"/>
                    <label text="Default markup"/> <!-- SCIPIO: NOTE: at time of writing this defaults to "p" -->
                    <label style="p" text="Paragraph"/>
                    <label style="span" text="Span"/>
                    <label style="div" text="Div"/>
                    <label style="myclass" text="Generic markup (with extra class)"/>
                    <label style="+myclass" text="Generic markup (with extra class)"/>
                    <label style="generic:myclass" text="Generic markup (with extra class)"/>
                    <label style="generic:+myclass" text="Generic markup (with extra class)"/>
                    <label style="p:myclass" text="Paragraph (with extra class)"/>
                    <label style="span:+myclass" text="Span (with extra class)"/>
                    <label style="div:+myclass" text="Div (with extra class)"/>
                </screenlet>
                <screenlet title="Common message labels">
                    <label style="common-msg-result" text="Result message"/>
                    <label style="common-msg-result-norecord" text=" "/>
                    <label style="common-msg-warning" text="General warning message"/>
                    <label style="common-msg-error" text="General error message"/>
                    <label style="common-msg-error-perm" text="Permission error message"/>
                    <label style="common-msg-error-security" text="Security error message"/>
                    <label style="common-msg-custom" text="Custom common message"/>
                    <label style="common-msg-error:+myclass" text="Error message (with extra class)"/>
                    <label style="common-msg-error:myclass" text="Error message (with extra class that replaces default)"/>
                    <label style="common-msg-info" text="Regular info message"/>
                    <label style="common-msg-info-important" text="Important info message"/>
                </screenlet>
                <screenlet title="Widget menus">
                    <label style="heading" text="Nested button menu (markup test only)" />
                    <include-menu name="LayoutDemoButton2" location="component://webtools/widget/MiscMenus.xml"/>
                    <include-menu name="LayoutDemoNestedButton" location="component://webtools/widget/MiscMenus.xml"/>
                    <include-menu name="LayoutDemoButtonDropdown" location="component://webtools/widget/MiscMenus.xml"/>
                    
                    <screenlet title="Scope sharing test">
                        <include-menu name="LayoutDemoTest2" location="component://webtools/widget/MiscMenus.xml" share-scope="false"/>
                        <label text="demoTestVar1 value (share-scope test): &quot;${demoTestVar1}&quot; (should be &quot;&quot;)" />
                        <include-menu name="LayoutDemoTest2" location="component://webtools/widget/MiscMenus.xml" share-scope="true"/>
                        <label text="demoTestVar1 value (share-scope test): &quot;${demoTestVar1}&quot; (should be &quot;demoTestValue1&quot;)" />
                    </screenlet>
                    
                    <screenlet title="Depth limit test">
                        <label text="Full (default/-1)" style="heading"/>
                        <include-menu name="LayoutDemoTest3" location="component://webtools/widget/MiscMenus.xml" max-depth="-1"/>
                        <label text="max-depth 2" style="heading"/>
                        <include-menu name="LayoutDemoTest3" location="component://webtools/widget/MiscMenus.xml" max-depth="2"/>
                        <label text="max-depth 1" style="heading"/>
                        <include-menu name="LayoutDemoTest3" location="component://webtools/widget/MiscMenus.xml" max-depth="1"/>
                        <label text="sub-menus 'none' filter (same as max-depth 1)" style="heading"/>
                        <include-menu name="LayoutDemoTest3" location="component://webtools/widget/MiscMenus.xml" max-depth="-1" sub-menus="none"/>
                    </screenlet>
                    
                    <screenlet title="Screen widget include-screens directive test">
                        <screenlet title="Regular widget screens">
                            <label style="p">The following simply includes two local screens that were included from another file with include-screens directive.
                                Because the target includes were regular screens containing widgets, they were created in our local file by include-screens using simple
                                delegating directives containing the legacy include-screen directive. No surprises here.</label>
                            <include-screen name="DemoExtraWidget1"/>
                            <include-screen name="DemoExtraWidget2"/>
                        </screenlet>
                        <screenlet title="Actions-only screens">
                            <section share-scope="false">
                                <actions>
                                    <!-- these succeed if the vars print out at all -->
                                    <include-screen-actions name="DemoExtraActions1"/>
                                    <include-screen-actions name="DemoExtraActions2"/>
                                    <include-screen-actions name="DemoExtraActions3"/>
                                    <include-screen-actions name="DemoExtraActions4"/>
                                </actions>
                                <widgets>
                                    <label style="p">The following tests the actions includes produced by include-screens directive.
                                        In the next, the first two should print because they contained only actions, so they were implemented by include-screens with an include-screen-actions delegate/placeholder,
                                        and this ensures the include-screen-actions we just ran work transitively and succeed.
                                        The two after should come up blank because they contained widgets and condition, so include-screens implemented their delegates with include-screen, and
                                        the include-screen-actions we just ran above is not able to follow those.
                                        This highlights the importance of creating the right kind of screens, in order for reuse to work after.</label>
                                    <label text="demoExtraActions1Msg: ${demoExtraActions1Msg}"/>
                                    <label text="demoExtraActions2Msg: ${demoExtraActions2Msg}"/>
                                    <label text="demoExtraActions3Msg (should be empty, contained widgets): ${demoExtraActions3Msg}"/>
                                    <label text="demoExtraActions4Msg (should be empty, contained condition): ${demoExtraActions4Msg}"/>
                                    <label text="Now print the third one within its widget, and it should only show this way:"/>
                                    <include-screen name="DemoExtraActions3"/>
                                </widgets>
                            </section>
                        </screenlet>
                    </screenlet>
                    
                    <screenlet title="New widget condition-to-field element">
                        <section share-scope="false">
                            <actions>
                                <set field="testField1" value="someValue"/>
                                <set field="testField2" value="someValue2"/>
                                
                                <condition-to-field field="boolRes1" type="Boolean">
                                    <if-compare field="testField1" operator="equals" value="someValue"/>
                                </condition-to-field>
                                <condition-to-field field="boolRes2" type="Boolean">
                                    <if-compare field="testField1" operator="equals" value="NOTsomeValue"/>
                                </condition-to-field>
                                
                                <condition-to-field field="indicatorRes1" type="Indicator">
                                    <and>
                                        <if-compare field="testField1" operator="equals" value="someValue"/>
                                        <if-compare field="testField2" operator="equals" value="someValue2"/>
                                    </and>
                                </condition-to-field>
                                <condition-to-field field="indicatorRes2" type="Indicator">
                                    <and>
                                        <if-compare field="testField1" operator="not-equals" value="someValue"/>
                                        <if-compare field="testField2" operator="equals" value="someValue2"/>
                                    </and>
                                </condition-to-field>
                                
                                <condition-to-field field="stringRes1" type="String">
                                    <and>
                                        <if-compare field="testField1" operator="equals" value="someValue"/>
                                    </and>
                                </condition-to-field>
                                <condition-to-field field="stringRes2" type="PlainString" fail-value="this is fail-value with some interpolated field ${testField2}">
                                    <and>
                                        <if-compare field="testField1" operator="equals" value="someValue"/>
                                        <if-compare field="testField2" operator="not-equals" value="someValue2"/>
                                    </and>
                                </condition-to-field>
                                
                                <condition-to-field field="mapRes1" type="Map" pass-value="{hey=you, its=me}">
                                    <or>
                                        <if-compare field="testField1" operator="equals" value="someValue"/>
                                    </or>
                                </condition-to-field>
                                <condition-to-field field="mapRes2" type="Map" pass-value="{hey=you, its=me}"><!-- tests null -->
                                    <or>
                                        <if-compare field="testField1" operator="not-equals" value="someValue"/>
                                    </or>
                                </condition-to-field>
                                
                                <condition-to-field field="testMap.testBoolList[]">
                                    <if-compare field="testField1" operator="equals" value="someValue"/>
                                </condition-to-field>
                                <condition-to-field field="testMap.testBoolList[]" type="Boolean">
                                    <if-compare field="testField1" operator="equals" value="NOTsomeValue"/>
                                </condition-to-field>
                                
                                <set field="boolRes3" value="this is non-empty, won't be overridden"/>
                                <condition-to-field field="boolRes3" type="Boolean" only-if-field="empty">
                                    <if-compare field="testField1" operator="equals" value="someValue"/>
                                </condition-to-field>
                                <set field="boolRes4" value=""/>
                                <condition-to-field field="boolRes4" type="Boolean" only-if-field="empty">
                                    <if-compare field="testField1" operator="equals" value="someValue"/>
                                </condition-to-field>
                                
                                <condition-to-field field="commonSideBarMenuEmu.cond" type="Boolean" only-if-field="empty">
                                    <or><!-- SPECIAL: Catalog allows Create and Update to stand in for View -->
                                        <if-has-permission permission="CATALOG" action="_ADMIN"/>
                                        <if-has-permission permission="CATALOG" action="_CREATE"/>
                                        <if-has-permission permission="CATALOG" action="_UPDATE"/>
                                        <if-has-permission permission="CATALOG" action="_VIEW"/>
                                    </or>
                                </condition-to-field>
                                
                                <set field="testField5" type="Boolean" value="true"/>
                                <condition-to-field field="boolRes5" type="Boolean" only-if-field="empty">
                                    <if-compare field="testField5" operator="not-equals" type="Boolean" value="false"/>
                                </condition-to-field>
                                <set field="testField5" type="Boolean" value="" set-if-null="true"/>
                                <condition-to-field field="boolRes6" type="Boolean" only-if-field="empty">
                                    <if-compare field="testField5" operator="not-equals" type="Boolean" value="false"/>
                                </condition-to-field>
                                <set field="testField5" type="Boolean" value="false"/>
                                <condition-to-field field="boolRes7" type="Boolean" only-if-field="empty">
                                    <if-compare field="testField5" operator="not-equals" type="Boolean" value="false"/>
                                </condition-to-field>
                            </actions>
                            <widgets>
                                <label text="boolRes1: '${boolRes1}'"/>
                                <label text="boolRes2: '${boolRes2}'"/>
                                <label text="indicatorRes1: '${indicatorRes1}'"/>
                                <label text="indicatorRes2: '${indicatorRes2}'"/>
                                <label text="stringRes1: '${stringRes1}'"/>
                                <label text="stringRes2: '${stringRes2}'"/>
                                <label text="mapRes1: '${mapRes1}'"/>
                                <label text="mapRes2 (should be null/empty): '${mapRes2}'"/>
                                <label text="testMap.testBoolList: '${testMap.testBoolList}'"/>
                                <label text="boolRes3 (only-if-field='empty'): '${boolRes3}'"/>
                                <label text="boolRes4 (only-if-field='empty'): '${boolRes4}'"/>
                                <label text="commonSideBarMenuEmu.cond: '${commonSideBarMenuEmu.cond}'"/>
                                <label text="boolRes5 (should be true): '${boolRes5}'"/>
                                <label text="boolRes6 (should be true): '${boolRes6}'"/>
                                <label text="boolRes7 (should be false): '${boolRes7}'"/>
                            </widgets>
                        </section>
                    </screenlet>
                    
                    <screenlet title="Screen inline FTL templates and inline groovy scripts">
                        <section>
                            <actions>
                                <!-- NOTE: The script type must be specified for inline scripts, either as own attribute (new in Scipio)
                                    or with prefix-colon syntax (stock ofbiz method): -->
                                <script lang="groovy"><![CDATA[
                                    import org.ofbiz.base.util.*;
                                    Debug.logInfo("Running from inline groovy script!", "LayoutDemoInline.groovy");
                                    context.myVarFromInlineGroovy1 = "This was assigned from within inline groovy script & it's working great!";
                                ]]></script>
                                <!-- NOTE: The default for trim-lines is true, meaning the left and right spaces in the xml disappear from the script
                                    before it is passed to the interpreter/compiler.
                                    If a script is negatively affected (rare but possible), false can be specified, in which case all the extra whitespace
                                    in the XML then gets included in the script passed to the interpreter/compiler. -->
                                <script trim-lines="false"><![CDATA[groovy:
                                    import org.ofbiz.base.util.*;
                                    Debug.logInfo("Running from inline groovy script 2!", "LayoutDemoInline.groovy");
                                ]]></script>
                            </actions>
                            <widgets>
                                <platform-specific>
                                    <html><html-template><![CDATA[
                                        <#assign myVar = "This was assigned within inline freemarker template!">
                                        <@row>
                                          <@cell>
                                            <@alert type="info">${myVar}</@alert>
                                          </@cell>
                                        </@row>
                                    ]]></html-template></html>
                                </platform-specific>
                                <platform-specific>
                                    <html><html-template lang="ftl"><![CDATA[
                                        <@row>
                                          <@cell>
                                            <@alert type="info">Second inline template! Explicit type (default is ftl anyway).<br/>
                                                myVarFromInlineGroovy1: ${myVarFromInlineGroovy1}</@alert>
                                          </@cell>
                                        </@row>
                                    ]]></html-template></html>
                                </platform-specific>
                                <platform-specific>
                                    <html><html-template trim-lines="false"><![CDATA[ftl:
                                        <@row>
                                          <@cell>
                                            <@alert type="info">Third inline template, with colon-prefixed type, fully redundant.</@alert>
                                          </@cell>
                                        </@row>
                                    ]]></html-template></html>
                                </platform-specific>
                            </widgets>
                        </section>
                    </screenlet>
                    
                    <screenlet title="New include directive actions (post-context-stack-push)">
                        <section share-scope="false">
                            <actions>
                                <set field="mySimpleVar1" value="OutsideValue"/>
                                <script lang="groovy"><![CDATA[
                                    public class TestUtil {
                                        def logVars(context, label) {
                                            org.ofbiz.base.util.Debug.logInfo(label + ": mySimpleVar1: " + context.mySimpleVar1
                                                + "; mySimpleVar2: " + context.mySimpleVar2, "IncludeActionsTestGroovy");
                                        }
                                    }
                                    context.testUtil = new TestUtil();
                                    context.remove("mySimpleVar2");
                                ]]></script>
                            </actions>
                            <widgets>
                                <section>
                                    <actions>
                                        <script lang="groovy"><![CDATA[ context.testUtil.logVars(context, "pre-include, pre-stack-push"); ]]></script>
                                    </actions>
                                    <widgets>
                                        <label text="Hello from before include directive. mySimpleVar1: ${groovy: context.mySimpleVar1 ?: 'missing'}. mySimpleVar2: ${groovy: context.mySimpleVar2 ?: 'missing'}."/>
                                        <include-screen name="DemoLabelWidgetWithVars">
                                            <actions>
                                                <set field="mySimpleVar1" value="InnerStackValue"/>
                                                <set field="mySimpleVar2" value="InnerStackValue"/>
                                                <script lang="groovy"><![CDATA[ context.testUtil.logVars(context, "pre-include, post-stack-push"); ]]></script>
                                            </actions>
                                        </include-screen>
                                        <section>
                                            <actions>
                                                <script lang="groovy"><![CDATA[ context.testUtil.logVars(context, "post-include, post-stack-pop"); ]]></script>
                                            </actions>
                                            <widgets>
                                                <label text="Hello from after include directive (stack popped). mySimpleVar1: ${groovy: context.mySimpleVar1 ?: 'missing'}. mySimpleVar2: ${groovy: context.mySimpleVar2 ?: 'missing'}."/>
                                            </widgets>
                                        </section>
                                    </widgets>
                                </section>
                            </widgets>
                        </section>
                    </screenlet>
                    
                    <screenlet title="New conditional element tests (if, if-widget)">
                        <section>
                            <actions>
                                <set field="testField1" value="true"/>
                                <if>
                                    <condition><if-true field="testField1"/></condition>
                                    <then><set field="resField1" value="if block"/></then>
                                    <else-if>
                                        <condition><if-false field="testField1"/></condition>
                                        <then><set field="resField1" value="else-if block"/></then>
                                    </else-if>
                                    <else>
                                        <set field="resField1" value="else block"/>
                                    </else>
                                </if>
                                <set field="testField1" value="false"/>
                                <if>
                                    <condition><if-true field="testField1"/></condition>
                                    <then><set field="resField2" value="if block"/></then>
                                    <else-if>
                                        <condition><if-false field="testField1"/></condition>
                                        <then><set field="resField2" value="else-if block"/></then>
                                    </else-if>
                                    <else>
                                        <set field="resField2" value="else block"/>
                                    </else>
                                </if>
                                <!-- the errors pollute the log; don't need to test this every time
                                <set field="testField1" value="other"/>
                                <if>
                                    <condition><if-true field="testField1"/></condition>
                                    <then><set field="resField3" value="if block"/></then>
                                    <else-if>
                                        <condition><if-false field="testField1"/></condition>
                                        <then><set field="resField3" value="else-if block"/></then>
                                    </else-if>
                                    <else>
                                        <set field="resField3" value="else block"/>
                                    </else>
                                </if>-->
                                <set field="testField1" value="other"/>
                                <if>
                                    <condition><if-true value="${testField1 == 'other'}"/></condition>
                                    <then><set field="resField4" value="if block"/></then>
                                    <else-if>
                                        <condition><if-false field="testField1"/></condition>
                                        <then><set field="resField4" value="else-if block"/></then>
                                    </else-if>
                                    <else>
                                        <set field="resField4" value="else block"/>
                                    </else>
                                </if>
                                <set field="testField1" value="other"/>
                                <if condition="${testField1 == 'other'}">
                                    <then><set field="resField5" value="if block"/></then>
                                    <else-if>
                                        <condition><if-false field="testField1"/></condition>
                                        <then><set field="resField5" value="else-if block"/></then>
                                    </else-if>
                                    <else>
                                        <set field="resField5" value="else block"/>
                                    </else>
                                </if>
                                
                                <condition-to-field field="existsCrazyWidget1">
                                    <if-widget operator="defined" type="screen" location="${parameters.mainDecoratorLocation}" name="crazyWidget1" />
                                </condition-to-field>
                                <condition-to-field field="existsMainDecorator">
                                    <if-widget operator="defined" type="screen" location="${parameters.mainDecoratorLocation}" name="main-decorator" />
                                </condition-to-field>
                                <condition-to-field field="existsFormWidgetProgramExport">
                                    <if-widget operator="defined" type="form" location="component://webtools/widget/MiscForms.xml" name="ProgramExport" />
                                </condition-to-field>
                                <condition-to-field field="existsFormWidgetRidiculous">
                                    <if-widget operator="defined" type="form" location="component://webtools/widget/MiscForms.xml" name="Ridiculous" />
                                </condition-to-field>
                                <condition-to-field field="existsMenuWidgetRidiculous">
                                    <if-widget operator="defined" type="menu" location="component://webtools/widget/Menus.xml" name="Ridiculous" />
                                </condition-to-field>
                                <condition-to-field field="existsMenuWidgetWebtoolsAppBar">
                                    <if-widget operator="defined" type="menu" location="component://webtools/widget/Menus.xml" name="WebtoolsAppBar" />
                                </condition-to-field>
                            </actions>
                            <widgets>
                                <label text="resField1: ${resField1}"/>
                                <label text="resField2: ${resField2}"/>
                                <label text="resField3: ${resField3}"/>
                                <label text="resField4: ${resField4}"/>
                                <label text="resField5: ${resField5}"/>

                                <label text="existsCrazyWidget1: ${existsCrazyWidget1}"/>
                                <label text="existsMainDecorator: ${existsMainDecorator}"/>
                                <label text="existsFormWidgetProgramExport: ${existsFormWidgetProgramExport}"/>
                                <label text="existsFormWidgetRidiculous: ${existsFormWidgetRidiculous}"/>
                                <label text="existsMenuWidgetRidiculous: ${existsMenuWidgetRidiculous}"/>
                                <label text="existsMenuWidgetWebtoolsAppBar: ${existsMenuWidgetWebtoolsAppBar}"/>
                            </widgets>
                        </section>
                    </screenlet>
                </screenlet>
                <include-screen name="CatchActionsTest"/>
            </widgets>
        </section>
    </screen>
    
    <screen name="TargetedRenderingTest">
        <section>
            <actions>
                <set field="title" value="Targeted Rendering Test"/>
                <set field="activeSubMenu" from-field="activeSubMenu" default-value="LayoutDemo" />
                <set field="activeSubMenuItem" value="${groovy: (context.debugMode ? 'LayoutDemoDebug' : 'LayoutDemo')}"/>
            </actions>
            <widgets>
                <decorator-screen name="CommonWebtoolsAppDecorator" location="${parameters.mainDecoratorLocation}">
                    <decorator-section name="body">
                        <section name="TR-Widget-Section-1">
                            <condition>
                                <if-has-permission permission="OFBTOOLS" action="_VIEW"/>
                            </condition>
                            <widgets>
                                <container id="tr-widget-container-1">
                                    <platform-specific>
                                        <html><html-template location="component://webtools/webapp/webtools/layout/targetedrenderingtest.ftl"/></html>
                                    </platform-specific>
                                </container>
                                <container id="tr-widget-container-2">
                                    <decorator-screen name="TargetedRenderingTestSubDecorator">
                                        <decorator-section name="body">
                                            <container id="tr-widget-container-3">
                                                <label text="Hello from sub-decorator body"/>
                                            </container>
                                        </decorator-section>
                                    </decorator-screen>
                                </container>
                            </widgets>
                            <fail-widgets>
                                <label style="common-msg-error-perm">${uiLabelMap.WebtoolsViewPermissionError}</label>
                            </fail-widgets>
                        </section>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>
    
    <screen name="TargetedRenderingTestDeepWidget1">
        <section name="TR-Widget-Deep-Section-2">
            <widgets><label text="Hello from widget within ftl file"/></widgets>
        </section>
    </screen>
    
    <screen name="TargetedRenderingTestSubDecorator">
        <section name="TR-SubDec-Section-Top">
            <widgets>
                <section name="TR-SubDec-Section-1">
                    <widgets>
                        <screenlet id="tr-subdec-screenlet-1">
                            <platform-specific><html><html-template><![CDATA[
                            <@virtualSection name="tr-subdec-ftl-virtual-1">
                                <div>
                                    <p>We are inside sub decorator section 1</p>
                                </div>
                            </@virtualSection>
                            ]]></html-template></html></platform-specific>
                        </screenlet>
                    </widgets>
                </section>
                <section name="TR-SubDec-Section-2">
                    <widgets>
                        <screenlet id="tr-subdec-screenlet-2">
                            <platform-specific><html><html-template><![CDATA[
                            <@virtualSection name="tr-subdec-ftl-virtual-2">
                                <div>
                                    <p>We are inside sub decorator section 2</p>
                                    <@render type="section" name="body"/>
                                    <p>We are inside sub decorator section 2</p>
                                </div>
                            </@virtualSection>
                            ]]></html-template></html></platform-specific>
                        </screenlet>
                    </widgets>
                </section>
            </widgets>
        </section>
    </screen>

    <screen name="TemplateTest">
        <section>
            <actions>
                <property-map resource="CMSUiLabels" map-name="uiLabelMap" global="true"/>                
                <set field="titleProperty" value="WebtoolsTemplateTest"/>
                <set field="activeSubMenu" from-field="activeSubMenu" default-value="Development" />
                <set field="activeSubMenuItem" value="TemplateTest"/>
                <include-screen-actions name="CodeEditorCommonIncludes" location="component://cms/widget/CommonScreens.xml"/>
                <property-to-field resource="webtools" property="dev.script.tools.enabled" field="tmplTestEnabled"/>
                <set field="tmplTestEnabled" from-field="tmplTestEnabled" type="Boolean"/>
                <condition-to-field field="hasTmplTestPerm" type="Boolean">
                    <and>
                        <if-has-permission permission="OFBTOOLS" action="_VIEW"/>
                        <if-has-permission permission="ENTITY_DATA_ADMIN"/><!-- SUPER/FULLADMIN only, for security reasons -->
                        <if-true field="tmplTestEnabled"/>
                    </and>
                </condition-to-field>
                <script lang="groovy"><![CDATA[
                    import javax.transaction.Transaction;
                    import org.ofbiz.base.util.*;
                    import org.ofbiz.entity.transaction.*;
                    final module = "TemplateTest.groovy";

                    scriptBody = parameters.scriptBody as String;
                    templateBody = parameters.templateBody as String;

                    execDefault = (scriptBody == null && templateBody == null);
                    if (scriptBody == null) {
                        scriptBody = "import org.ofbiz.base.util.*;\n" +
                            "import org.ofbiz.entity.condition.*;\n" +
                            "import org.ofbiz.entity.util.*;\n" +
                            "\n" +
                            "final module = \"TemplateTest.groovy\";\n" +
                            "\n" +
                            "userParty = from(\"Party\").select(\"partyId\", \"partyTypeId\").where(\"partyId\", context.userLogin?.partyId).queryOne();\n" +
                            "\n" +
                            "Debug.logInfo(\"Hello from test script and user party: \" + userParty, module);\n" +
                            "\n" +
                            "context.testVar1 = \"This is a test string value from groovy from user party: \" + userParty;\n";
                    }
                    if (templateBody == null) {
                        templateBody = "<#assign ftlTestVar1 = testVar1!>" +
                            "\n" +
                            "\n<p><strong>testVar1:</strong> <em>\${escapeVal(ftlTestVar1, 'htmlmarkup')}</em>";
                    }

                    execTemplate = (execDefault || request.getMethod().toLowerCase() == "post") && context.hasTmplTestPerm == true; // security
                    if (execTemplate && scriptBody) {
                        Transaction suspendedTransaction = null;
                        try {
                            if (TransactionUtil.isTransactionInPlace()) { // SCIPIO: 2018-09-04: added check to eliminate useless warnings
                                suspendedTransaction = TransactionUtil.suspend();
                            }
                            beganTransaction = false;
                            try {
                                beganTransaction = TransactionUtil.begin(72000);
                                GroovyUtil.evalBlock(scriptBody, context, false);
                                TransactionUtil.commit(beganTransaction);
                            } catch (Exception e) {
                                Debug.logError(e, "Error evaluating Groovy script", module);
                                errorMessageList = context.errorMessageList ?: [];
                                errorMessageList.add("Error evaluating Groovy script: " + e.toString());
                                context.errorMessageList = errorMessageList;
                                try {
                                    TransactionUtil.rollback(beganTransaction, "Error evaluating Groovy script", e);
                                } catch (GenericTransactionException e2) {
                                    Debug.logError(e2, "Unable to rollback transaction", module);
                                }
                            }
                        } finally {
                            if (suspendedTransaction != null) {
                                try {
                                    TransactionUtil.resume(suspendedTransaction);
                                } catch (GenericTransactionException e) {
                                    Debug.logError(e, "Error resuming suspended transaction", module);
                                }
                            }
                        }
                    }

                    context.scriptBody = scriptBody;
                    context.templateBody = templateBody;
                    context.execDefault = execDefault;
                    context.execTemplate = execTemplate;
                ]]></script>
            </actions>
            <widgets>
                <decorator-screen name="CommonWebtoolsAppDecorator" location="${parameters.mainDecoratorLocation}">
                    <decorator-section name="body">
                        <section>
                            <condition>
                                <and>
                                    <if-has-permission permission="OFBTOOLS" action="_VIEW"/>
                                    <if-has-permission permission="ENTITY_DATA_ADMIN"/><!-- SUPER/FULLADMIN only, for security reasons -->
                                </and>
                            </condition>
                            <widgets>
                                <section>
                                    <condition>
                                        <not><if-true field="tmplTestEnabled"/></not>
                                    </condition>
                                    <widgets>
                                        <label style="common-msg-warning">${uiLabelMap.CommonFunctionIsDisabled}</label>
                                    </widgets>
                                </section>
                                <platform-specific><html><html-template><![CDATA[
                                  <@script>
                                    $(document).ready(function() {
                                        CodeMirror.fromTextArea($('textarea#scriptBody')[0], {
                                            lineNumbers: true,
                                            matchBrackets: true,
                                            mode: "groovy",
                                            indentUnit: 4,
                                            indentWithTabs: ${indentWithTabs?string},
                                            foldGutter: true,
                                            gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
                                            extraKeys: {"Ctrl-Space": "autocomplete"}
                                            }).on('change', function(cMirror){
                                                $('textarea#scriptBody')[0].value = cMirror.getValue();
                                            }
                                        );
                                        CodeMirror.fromTextArea($('textarea#templateBody')[0], {
                                            lineNumbers: true,
                                            matchBrackets: true,
                                            mode: "freemarker",
                                            indentUnit: 4,
                                            indentWithTabs: ${indentWithTabs?string},
                                            foldGutter: true,
                                            gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
                                            extraKeys: {"Ctrl-Space": "autocomplete"}
                                            }).on('change', function(cMirror){
                                                $('textarea#templateBody')[0].value = cMirror.getValue();
                                            }
                                        );
                                    });
                                  </@script>
                                  <@section class="+cms-edit-elem cms-edit-template">
                                    <@form method="post" id="editorForm" action=makePageUrl("TemplateTest")>
                                       <@section class="+editorContent">
                                          <@fields type="default-compact">
                                            <@field label=(rawLabel('CmsScriptBody')+" (Groovy)") type="textarea" class="+editor" 
                                                name="scriptBody" id="scriptBody" value=(scriptBody!"") rows=30/>
                                            <@field label=(rawLabel('CmsTemplateBody')+" (Freemarker)") type="textarea" class="+editor" 
                                                name="templateBody" id="templateBody" value=(templateBody!"") rows=30/>
                                          </@fields>
                                          <style type="text/css">
                                            .CodeMirror-hints {font-size:1em;}
                                          </style>
                                       </@section>
                                       <@field type="submit"/>
                                    </@form>
                                  </@section>
                                   
                                  <#-- FREEMARKER OUTPUT -->
                                  <#if execTemplate>
                                    <@section title=uiLabelMap.CmsOutput>
                                      <#assign tmplBodyCode = raw(templateBody!"")?interpret>
                                      <#assign tmplBodyOut><@tmplBodyCode/></#assign>
                                      ${tmplBodyOut}
                                    </@section>
                                    <@section title=uiLabelMap.CmsRawOutput>
                                      ${tmplBodyOut?html}
                                    </@section>
                                  </#if>
                                ]]></html-template></html></platform-specific>
                            </widgets>
                            <fail-widgets>
                                <label style="common-msg-error-perm">${uiLabelMap.WebtoolsPermissionError}</label>
                            </fail-widgets>
                        </section>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>

    <screen name="validateSystemLocations">
        <section>
            <actions>
                <script lang="groovy"><![CDATA[
                    vslResults = null;
                    if (parameters.vslPaths || parameters.vslClassNames) {
                        vslResults = dispatcher.runSync("validateSystemLocations", 
                            [userLogin:context.userLogin, paths: parameters.vslPaths, classNames: parameters.vslClassNames]);
                    }
                    context.vslResults = vslResults;
                ]]></script>
            </actions>
            <widgets>
                <platform-specific><html><html-template><![CDATA[
                    <form method="post" action="<@pageUrl uri=raw(vslTargetUri)/>">
                        <@field type="textarea" name="vslPaths" label="Paths" value=(parameters.vslPaths!)/>
                        <@field type="textarea" name="vslClassNames" label="Class names" value=(parameters.vslClassNames!)/>
                        <@field type="submit"/>
                    </form>
                    <#if vslResults??>
                      <@section title="Results:">
                      <#if vslResults.pathResults??>
                        <@section title="Valid paths:">
                          <ul>
                            <#list vslResults.pathResults as vslResult>
                              <#if vslResult.valid>
                                <li>${vslResult.value}</li>
                              </#if>
                            </#list>
                          </ul>
                        </@section>
                        <@section title="Invalid paths:">
                          <ul>
                            <#list vslResults.pathResults as vslResult>
                              <#if !vslResult.valid>
                                <li>${vslResult.value}: ${vslResult.errMsg!}</li>
                              </#if>
                            </#list>
                          </ul>
                        </@section>
                      </#if>
                      <#if vslResults.classNameResults??>
                        <@section title="Valid class names:">
                          <ul>
                            <#list vslResults.classNameResults as vslResult>
                              <#if vslResult.valid>
                                <li>${vslResult.value}</li>
                              </#if>
                            </#list>
                          </ul>
                        </@section>
                        <@section title="Invalid class names:">
                          <ul>
                            <#list vslResults.classNameResults as vslResult>
                              <#if !vslResult.valid>
                                <li>${vslResult.value}: ${vslResult.errMsg!}</li>
                              </#if>
                            </#list>
                          </ul>
                        </@section>
                      </#if>
                      </@section>
                    </#if>
                ]]></html-template></html></platform-specific>
            </widgets>
        </section>
    </screen>

    <screen name="CatchActionsTest">
        <section>
            <actions>
                <script lang="groovy"><![CDATA[
                    context.testIt = delegator.query().from("WebSite").queryIterator();
                    class CatchActionsTestException extends RuntimeException {}
                    context.testException = new CatchActionsTestException();
                    Debug.logInfo("CatchActionsTest: throwing exception: " + context.testException, "CatchActionsTest.groovy");
                    // NOTE: this can be used, but there is extra ugly warning from ScriptUtil
                    //throw context.testException;
                ]]></script>
                <throw-exception field="testException"/>
            </actions>
            <widgets>
            </widgets>
            <catch-actions>
                <script lang="groovy"><![CDATA[
                    Debug.logInfo("CatchActionsTest: catch-actions: caught exception: " + context.scpException, "CatchActionsTest.groovy");
                ]]></script>
                <!-- can rethrow like this, but here we want to prevent the crash
                <throw-exception field="scpException"/>-->
            </catch-actions>
            <finally-actions>
                <script lang="groovy"><![CDATA[
                    Debug.logInfo("CatchActionsTest: finally-actions: closing EntityListIterator", "CatchActionsTest.groovy");
                ]]></script>
                <close-object field="testIt"/>
            </finally-actions>
        </section>
    </screen>

    <screen name="hotwireTest">
        <section>
            <actions>
                <!-- NOTE: OFBTOOLS rights implied by webapp (frontend needs check) -->
            </actions>
            <widgets>
                <platform-specific><html><html-template><![CDATA[
                    <@section title="Static Comments">
                        <@render resource="component://webtools/widget/MiscScreens.xml#hotwireStaticComments"/>
                    </@section>
                    <@section title="Websocket Comments">
                        <@render resource="component://webtools/widget/MiscScreens.xml#hotwireStreamCommentsSplash"/>
                    </@section>
                ]]></html-template></html></platform-specific>
            </widgets>
        </section>
    </screen>

    <screen name="hotwireActions">
        <actions>
            <set field="hotwire.enabled" from-field="hotwire.enabled" type="Boolean" default-value="true" global="true"/>
        </actions>
    </screen>

    <screen name="hotwireStaticComments">
        <section>
            <actions>
                <!-- NOTE: OFBTOOLS rights implied by webapp (frontend needs check) -->
                <script lang="groovy"><![CDATA[
                    context.hotwireComments = session.getAttribute('hotwireComments');
                ]]></script>
            </actions>
            <widgets>
                <platform-specific><html><html-template><![CDATA[
                    <turbo-frame id="hotwire-static-comments">
                        <div>
                            <#if hotwireComments?has_content>
                                <ol>
                                    <#list hotwireComments as comment>
                                        <li id="${'hotwire-comment-' + comment?index}">${comment}</li>
                                    </#list>
                                </ol>
                            <#else>
                                (no comments)
                            </#if>
                        </div>

                        <form action="<@pageUrl uri='hotwireStaticCommentsAdd'/>" method="post">
                            <input type="text" name="comment" id="hotwire-comment-input">
                            <button type="submit">Send</button>
                        </form>
                    </turbo-frame>

                    <form action="<@pageUrl uri='hotwireStaticCommentsRemove'/>" method="post" data-turbo-frame="hotwire-static-comments">
                        <button type="submit">Remove</button>
                    </form>
                ]]></html-template></html></platform-specific>
            </widgets>
        </section>
    </screen>

    <screen name="hotwireStreamCommentsSplash">
        <section>
            <actions>
                <!-- NOTE: OFBTOOLS rights implied by webapp (frontend needs check) -->
            </actions>
            <widgets>
                <platform-specific><html><html-template><![CDATA[
                    <ul id="hotwire-stream-comments"><li>First comment</li></ul>
                    <p>Last time: <span id="hotwire-stream-date">${nowTimestamp}</span></p>

                    <turbo-stream-connection src="<@appUrl uri='/ws-turbo/comment-demo/subscribe'/>"></turbo-stream-connection>

                    <p><em>Note: This form sends through websockets for demo purposes only, after which the comments
                        above are updated through a separate websocket push.</em></p>

                    <form action="<@pageUrl uri='hotwireStreamCommentsAdd'/>" method="post" data-turbo-frame="hotwire-stream-dummy-frame">
                        <input type="text" name="comment">
                        <button type="submit">Send</button>
                    </form>

                    <turbo-frame id="hotwire-stream-dummy-frame"></turbo-frame>
                ]]></html-template></html></platform-specific>
            </widgets>
        </section>
    </screen>

    <screen name="hotwireStreamComments">
        <section>
            <actions>
                <!-- NOTE: OFBTOOLS rights implied by webapp (frontend needs check) -->
                <set field="comment" value="test"/>
            </actions>
            <widgets>
                <platform-specific><html><html-template><![CDATA[
                    <turbo-stream action="append" target="hotwire-stream-comments">
                        <template>
                            <li>${nowTimestamp}: ${comment!}</li>
                        </template>
                    </turbo-stream>
                    <turbo-stream action="replace" target="hotwire-stream-date">
                        <template>
                            <span id="hotwire-stream-date">${nowTimestamp}</span>
                        </template>
                    </turbo-stream>
                ]]></html-template></html></platform-specific>
            </widgets>
        </section>
    </screen>

</screens>