The Overview

We created a dynamic group assignment page in order to assign campers and counselors for our summer camp. We had 26 groups with two counselors and 8-10 campers per group and needed to assign both counselors and campers by one of five tracks. Your requirements will certainly be different - we are just illustrating the approach with this recipe. I've recorded a short video to illustrate this.

The set up is pretty straightforward - there is one page with an HTML block with all of the HTML and Lava and two workflows. The workflows are attached to this recipe and the page content is included below.

The Page

We created this page in our "reports" hierarchy but it can be created anywhere you like. Once you create a new page, just add an HTML block to the page and paste in this code (note places where updates are needed below shown with "Note"):

<style>
    .row {
        padding-top: 10px;
    }
    .row-label {
        padding-top: 10px;
        padding-left: 10px;
    }
    .row-person {
        padding-top: 10px;
        padding-left: 30px;
    }
</style>
{% assign parentGroupId = 323824 %} <!-- Note: this is the parent group of all of the camper groups -->
<table class="table table-striped">
<thead> 
    <tr> 
        <th>Name</th>
        <th>Track</th>
        <th>Counselor(s)</th>
        <th>Add Counselor</th>        
        <th>Camper(s)</th>
        <th>Add Camper</th>        
    </tr>
</thead>    
    
<tbody>
<!-- Camp Rock camper groups -->
{% group where:'ParentGroupId=={{ parentGroupId }}' sort:'Name' securityenabled:'false' disableprefetchattribute:'true' %}
    {% for g in groupItems %}
        <!-- Note: Get track for this camper group - we created Track as a group member attribute on each group but you may not need this -->
        {% attribute where:'Key == "Track" && EntityTypeQualifierValue == {{ g.Id }}' securityenabled:'false' disableattributeprefetch:'true' limit:'1' %}
            {% definedvalue where:'Guid == "{{ attribute.DefaultValue }}"' securityenabled:'false' disableattributeprefetch:'true' limit:'1' %}
                {% assign track = definedvalue.Value %}
            {% enddefinedvalue %}
        {% endattribute %}
    
    <tr>
            {% groupmember expression:'GroupId == {{ g.Id }} && GroupRole.IsLeader == true' count:'true' securityenabled:'false' %}
                {% if count == 1 %}
                    {% assign leaderText = '1 counselor' %}
                {% else %}
                    {% assign leaderText = count | Append:' counselors' %}
                {% endif %}
            {% endgroupmember %}
            {% groupmember expression:'GroupId == {{ g.Id }} && GroupRole.IsLeader == false' count:'true' securityenabled:'false' %}
                {% if count == 1 %}
                    {% assign memberText = '1 camper' %}
                {% else %}
                    {% assign memberText = count | Append:' campers' %}
                {% endif %}
            {% endgroupmember %}
        <!-- Display group heading -->
        <td>
            <strong>{{ g.Name }}</strong>
        </td>
        <td>
            <strong>{{ track }}</strong>
        </td>        
        <td>
            <strong>{{ leaderText }}</strong><br>
            <!-- Note: replace 400 below with the workflow type Id for the Populate Campers workflow -->
            {% groupmember expression:'GroupId == {{ g.Id }} && GroupRole.IsLeader == true' securityenabled:'false' %}
                {% for gm in groupmemberItems %}
                    <a href="/WorkflowEntry/400?GroupMember={{ gm.Guid }}&RedirectURL=/CampRockRosters" class="btn btn-default btn-xs">X</a> {{ gm.Person.FullName }}<br>
                {% endfor %}
            {% endgroupmember %}
        </td>
        <td> <!-- Note: replace 401 below with the workflow type Id for the Remove From Group workflow -->
            {% groupmember expression:'GroupId == {{ g.Id }} && GroupRole.IsLeader == true' securityenabled:'false' %}
                <a href="/WorkflowEntry/401?Group={{ g.Guid }}&CampRockTrack={{ track }}&MemberType=1&RedirectURL=/CampRockRosters" class="btn btn-primary btn-sm">Add Counselors</a>
            {% endgroupmember %}
        </td>         
        <td>
            <strong>{{ memberText }}</strong><br>
            
            {% groupmember expression:'GroupId == {{ g.Id }} && GroupRole.IsLeader == false' securityenabled:'false' %}
                {% for gm in groupmemberItems %}
                    {% assign p = gm.Person %}
                    {% assign gender = p.Gender %}
                    {% assign sn = p | Attribute:'SNI-SpecialServices' %}
                    {% if sn == 'Yes' %}
                        {% assign snText = '*Special Needs' %}
                    {% else %}
                        {% assign snText = '' %}
                    {% endif %} <!-- Note: replace 400 below with the workflow type Id for the Populate Campers workflow -->
                    <a href="/WorkflowEntry/400?GroupMember={{ gm.Guid }}&RedirectURL=/CampRockRosters" class="btn btn-default btn-xs">X</a> {{ p.FullName }} <small>({{ p.Age }})&nbsp{{ gender }}&nbsp{{ snText }}</small><br>
                {% endfor %}
            {% endgroupmember %}
        </td>
        
        <!-- Display leaders/volunteers (member type 1) and campers (member type 2) for this group -->
        <td>   <!-- Note: replace 401 below with the workflow type Id for the Remove From Group workflow -->
            {% groupmember expression:'GroupId == {{ g.Id }} && GroupRole.IsLeader == false' securityenabled:'false' %}
                <a href="/WorkflowEntry/401?Group={{ g.Guid }}&CampRockTrack={{ track }}&MemberType=2&RedirectURL=/CampRockRosters" class="btn btn-primary btn-sm">Add Campers</a>
            {% endgroupmember %}
        </td>
    {% endfor %}
{% endgroup %}
  </tbody>
</table>