Search code examples
jenkinsgroovyjenkins-pipelinejenkins-pluginsjenkins-groovy

How to iterate over nested map or list in Groovy script for Jenkins activeChoices plugin?


My first job using activeChoicesParameter plugin, and quite a challenge. What I want to achieve is a list of checkboxes, grouped as "main" and "specific" with properly formatted HTML code. The list of possible choices (represented by checkboxes) should be derived from mapping for a specific identifier, represented by 'single select' drop-down list.

So the checkbox list I want to obtain in my build page should look like the following:

Expected list of choices

What I tried so far were:

test_group_map = [
  "id_1": [
    [test_group : "group_1", test_subgroup : ["subgroup_1", "subgroup_2", "subgroup_3"] ],
    [test_group : "group_2", test_subgroup : ["subgroup_4", "subgroup_5"] ],
  ],
]

html_to_be_rendered = ""

test_groups = test_group_map[ID]
test_groups.each { groups ->
  html_to_be_rendered = """
    ${html_to_be_rendered}
    <li style=\"list-style: none\">
      <input name=\"value\" alt=\"${groups.test_group}\" json=\"${groups.test_group}\" type=\"checkbox\" class=\" \" id=\"option\">
      <label title=\"${groups.test_group}\" class=\" \" for=\"option\">${groups.test_group}</label>
      <ul style=\"list-style: none\">
        <li>
          <input name=\"value\" alt=\"${groups.test_subgroup}\" json=\"${groups.test_subgroup}\" type=\"checkbox\" class=\"subOption\">
          <label title=\"${groups.test_subgroup}\" class=\" \">${groups.test_subgroup}</label>
        </li>
      </ul>
    </li>
"""
}

html_to_be_rendered = "${html_to_be_rendered}"

return html_to_be_rendered

which resulted in:

Approach with list of values

My second approach was the following:

test_group_map = [
  "id_1": [
    [test_group : "group_1", test_subgroup : "subgroup_1", test_subgroup : "subgroup_2", test_subgroup : "subgroup_3" ],
    [test_group : "group_2", test_subgroup : "subgroup_4", test_subgroup :  "subgroup_5" ],
  ],
]

html_to_be_rendered = ""

test_groups = test_group_map[ID]
test_groups.each { groups ->
  html_to_be_rendered = """
    ${html_to_be_rendered}
    <li style=\"list-style: none\">
      <input name=\"value\" alt=\"${groups.test_group}\" json=\"${groups.test_group}\" type=\"checkbox\" class=\" \" id=\"option\">
      <label title=\"${groups.test_group}\" class=\" \" for=\"option\">${groups.test_group}</label>
      <ul style=\"list-style: none\">
        <li>
          <input name=\"value\" alt=\"${groups.test_subgroup}\" json=\"${groups.test_subgroup}\" type=\"checkbox\" class=\"subOption\">
          <label title=\"${groups.test_subgroup}\" class=\" \">${groups.test_subgroup}</label>
        </li>
      </ul>
    </li>
"""
}

html_to_be_rendered = "${html_to_be_rendered}"

return html_to_be_rendered

which gave me the following result:

Approach with many values for one key

(Note, that enclosing the main part html_to_be_rendered variables actually contain some formatting HTML markups, so they are used; I just cut the values for readability)

I tried also iterating over values for 'subgroup' key, but Jenkins gave me nothing (which means HTML code produced from script is not proper, or as far as I understand Groovy script fails at runtime, and doesn't return any HTML).

So finally I believe there is a problem with either iterating over presented mapping, or mapping itself is a cause. Any advice will be appreciated.


Solution

  • If I understand correctly, in your first version you want to iterate through groups.test_subgroup. I added that iteration to your first version:

    test_group_map = [
            "id_1": [
                    [test_group : "group_1", test_subgroup : ["subgroup_1", "subgroup_2", "subgroup_3"] ],
                    [test_group : "group_2", test_subgroup : ["subgroup_4", "subgroup_5"] ],
            ],
    ]
    
    html_to_be_rendered = ""
    
    String ID = "id_1"
    test_groups = test_group_map[ID]
    
    test_groups.each { groups ->
        html_to_be_rendered = """
        ${html_to_be_rendered}
        <li style=\"list-style: none\">
          <input name=\"value\" alt=\"${groups.test_group}\" json=\"${groups.test_group}\" type=\"checkbox\" class=\" \" id=\"option\">
          <label title=\"${groups.test_group}\" class=\" \" for=\"option\">${groups.test_group}</label>
          <ul style=\"list-style: none\">
            <li>""" +
                groups.test_subgroup.collect { name -> """
              <input name=\"value\" alt=\"${name}\" json=\"${name}\" type=\"checkbox\" class=\"subOption\">
              <label title=\"${name}\" class=\" \">${name}</label>"""}.join('<br>') + """
            </li>
          </ul>
        </li>
    """
    }
    
    html_to_be_rendered = "${html_to_be_rendered}"
    
    println html_to_be_rendered
    

    If that is getting too ugly think about using HTML MarkupBuilder

    def writer = new StringWriter()
    def builder = new groovy.xml.MarkupBuilder(writer)
    
    builder.html {
        head {}
        body {
            mkp.yieldUnescaped html_to_be_rendered
    
            test_groups.each { groups ->
                li(style: "list-style: none") {
                    input(name: "value", alt: groups.test_group, json: groups.test_group, type: "checkbox", class: " ", id: "option")
                    label(title: groups.test_group, class: " ", for: "option", groups.test_group)
                    ul(style: "list-style: none"){
                        li {
                            groups.test_subgroup.each { name ->
                                input(name: "value", alt: name, json: name, type: "checkbox", class: "subOption")
                                label(title: name, class: " ", name)
                                br()
                            }
                        }
                    }
                }
            }
        }
    }
    
    println(writer.toString())
    

    I have not tested any of this in Jenkins.