Have you ever thought about ways to expand the capabilities of your Group Leader Toolbox? In 2019 Morgan Woods taught a breakout on ways to do this.  If you attended the 2019 conference you can access her talk HERE or have access to the 2019 takeaways, her takeaway was called: Power Tools Workflow Takeaway.

This takeaway has inspired me for some time to work on some group leader enhancements myself.

THE WHAT?

Each rock instance comes with a block called [Group Detail Lava]. This block is used on the external site within the Group Leader Toolbox.  This block displays 2 tabs for pages already built in rock. 

  • Roster
  • Attendance

Screen_Shot_2020-12-03_at_11.02.46.png








As in the example Morgan Woods gave us in 2019, I wanted to add a few tabs to my Group Leader Toolbox.

  • Share a Story
  • Group Prayer Request

THE WHY?

Share a Story - There are so many different types of small groups in our church.  Each group has so many stories that come out of them. Some stories are how their group impacted the community, while other stories might be how the group has impacted each other.  We wanted to create a way for a group leader to share any stories that come up with us.

Group Prayer Requests - Our small group leaders are committed to praying for group members each week. During group time they collect prayer requests and send them back out to the group in an email later in the week.  Often times these prayer requests may not get entered into Rock allowing our campus prayer teams the opportunity to pray for them.  We wanted to create a tab that allowed our group leaders the opportunity to 1: Enter prayer request from the group directly into Rock and 2: Give our group leaders access to see prayer requests submitted by group members in the last 30 days.

THE HOW?

  1. Create 2 new pages on your external site.
  2. Name them accordingly.
  3. In Advanced Settings of the page settings, be sure to set your context parameters to GroupId
  4. If you want them to appear in the same type of tab structure as the Roster and Attendance pages build them out with the same blocks that appear on the Roster or Attendance pages.

If you are interested in building a Share a Story tab, here is how I built that:

  1. Under Admin Tools, add a [Note Type] of entity type [Group].
  2. On the new page you built for Sharing a story, add the block [Notes] in the [Main] section under the [Group Detail Lava] block.
  3. Be sure to change the block settings to include the Note Type you just built and define the entity as group

We also decided that we wanted these notes to appear within the Group Viewer on the internal side of Rock. We added the same note block, with the same block settings to the Group Viewer page just under the [Group Member List] block. This way our staff can enter stories on behalf of Group Leaders, but they would also have the ability to view their stories from inside rock for months, years to come.

If you are interested in building a Group Prayer Request tab, here is how I built that:

Huge thanks to Michael Allen for processing with me and coming up with a few creative ways to pull this off!

  1. On the new page you built for Group Prayer Requests, add two blocks to the [Main] section under the [Group Detail Lava] block. 1: Workflow Entry  and  2: HTML
  2. The Workflow Entry block will be used to collect new prayer requests from the group leader.
  3. The HTML block will be used to display prayer request of active group members over the last 30 days.

Within the Workflow Entry block select a workflow that would allow you to submit prayer requests for your group. 

Within the HTML block, modify the block settings to allow [sql]

  • Here is the sql used in that block:

{% sql %} SELECT p.[FirstName] ,p.[LastName] ,pr.[CreatedDateTime] ,pr.[Text] FROM [PrayerRequest] pr JOIN [PersonAlias] pa ON pr.[RequestedByPersonAliasId] = pa.[Id] JOIN [Person] p ON pa.[PersonId] = p.[Id] JOIN [GroupMember] gm ON p.[Id] = gm.[PersonId] WHERE gm.[GroupId] = {{ PageParameter.GroupId | AsInteger | Default:'0' }} AND pr.[IsPublic] = 1 AND pr.[IsApproved] = 1 AND pr.[IsActive] = 1 AND pr.[CreatedDateTime] >= DATEADD(day,-30, getdate()) and pr.[CreatedDateTime] <= getdate() AND gm.[GroupMemberStatus] = 1 AND gm.[IsArchived] = 0 ORDER BY [CreatedDateTime] DESC {% endsql %} <div class="alert alert-info"> <h2>Group Member Prayer Requests</h2> (last 30 days)<br> <table class="table table-hover"> <tr> <th>Date</th> <th>Person</th> <th>Prayer</th> </tr> {% for prayer in results %} <tr> <td>{{ prayer.CreatedDateTime | Date:'MMM. d, yyyy' }}</td> <td>{{ prayer.FirstName }} {{ prayer.LastName }}</td> <td>{{ prayer.Text }}</td> </tr> {% endfor %} </table> </div>

Last Step - We need to display our tabs in the Group Leader Toolbox. In order to do this, you will need to modify the Lava used in the [Group Detail Lava] block on every page you want displayed. (Roster, Attendance etc)

I have made quite a few changes to our Group Leader Toolbox, so I thought I would share our lava here. Note: I added 3 tabs to our Group Leader Toolbox. Those tabs can be seen in lines 100-116 in this code:

{% comment %}
{% include '~~/Assets/Lava/GroupDetail.lava' %}
{% endcomment %}
{% if AllowedActions.View == true or AllowedActions.Edit == true or AllowedActions.Administrate == true %}
    {% assign countActive = -1 %}
    {% assign countInactive = -1 %}
    {% assign countPending = -1 %}
    {% for member in Group.Members %}
        {% case member.GroupMemberStatus %}
            {% when 'Active' %}
                {% assign countActive = countActive | Plus: 1 %}
            {% when 'Inactive' %}
                {% assign countInactive = countInactive | Plus: 1 %}
            {% when 'Pending' %}
                {% assign countPending = countPending | Plus: 1 %}
            {% else %}
        {% endcase %}
    {% endfor %}
    {% for groupLocation in Group.GroupLocations %}
        {% if groupLocation.Location.GeoPoint != '' %}
        <div class="packagesummary-image"
             style="background: url('https://maps.googleapis.com/maps/api/staticmap?size=1400x400&zoom=13&maptype=roadmap&markers={{ groupLocation.Location.GeoPoint }}&scale=2&key={{ 'Global' | Attribute:'GoogleAPIKey' }}') no-repeat center;
                    width: 100%;
                    height: 200px;">
        </div>
        {% endif %}
    {% endfor %}
    <h1>{{ Group.Name }}</h1>
    {{ Group.Description }}
    {% comment %}
    {% if Group.GroupType.GroupCapacityRule != 'None' and  Group.GroupCapacity != '' %}
        {% assign warningLevel = 'warning' %}
        {% if Group.GroupType.GroupCapacityRule == 'Hard' %}
            {% assign warningLevel = 'danger' %}
        {% endif %}
        {% assign activeMemberCount = countActive | Plus:1 %} {% comment %}the counter is zero based{% endcomment %}
        {% assign overageAmount = activeMemberCount | Minus:Group.GroupCapacity %}
        {% if overageAmount > 10 %}
            <div class="alert alert-{{ warningLevel }} margin-t-sm">This group is over capacity by {{ overageAmount }} {{ 'individual' | PluralizeForQuantity:overageAmount }}.</div>
        {% endif %}
    {% endif %}
    {% endcomment %}
        <div class="alert alert-info">
    <div class="row">
        <div class="col-md-12">
        <h4>Leaders:</h4>
            {% assign leadercount = 0 %}
                {% for member in Group.Members %}
                    {% if member.GroupRole.IsLeader and member.GroupMemberStatus == 1 %}
                        {% assign leadercount = leadercount | Plus:1 %}
                    {% endif %}
                {% endfor %}
            {% if leadercount > 0 %}
                <ul>
                    {% for member in Group.Members %}
                        {% if member.GroupRole.IsLeader %}
                            <li>{{ member.Person.FullName }} <small>({{ member.GroupRole.Name}})</small></li>
                        {% endif %}
                    {% endfor %}
                </ul>
            {% else %}
                <p>There are currently no leaders assigned to this group.</p>
            {% endif %}
        </div>
    </div>
    </div>
    <div class="well">
    <div class="row">
        <div class="col-md-12">
        <h4>Group Details:</h4>
        {% for attribute in Group.AttributeValues %}
			{% if attribute.Value != '' %}
				<strong>{{ attribute.AttributeName }}:</strong> {{ attribute.ValueFormatted }} <br />
			{% endif %}
        {% endfor %}
        </div>
    </div>
    </div>
    {% if AllowedActions.Edit == true %}
    <div class="actions margin-v-md clearfix">
        <a class="btn btn-default btn-sm pull-right" href="#" onclick="{{ Group.Id | Postback:'EditGroup' }}">Edit</a>
    </div>
    {% endif %}
    {% if LinkedPages.RosterPage != '' and  (LinkedPages.AttendancePage != '' or Group.GroupType.TakesAttendance == 'False') %}
        <ul class="nav nav-tabs margin-v-sm">
            {% if LinkedPages.RosterPage != '' %}
                {% if LinkedPages.RosterPage == CurrentPage.Path %}
                    <li role="presentation" class="active"><a href="{{ LinkedPages.RosterPage }}?GroupId={{ Group.Id }}">Roster</a></li>
                {% else %}
                    <li role="presentation"><a href="{{ LinkedPages.RosterPage }}?GroupId={{ Group.Id }}">Roster</a></li>
                {% endif %}
            {% endif %}
            {% if LinkedPages.AttendancePage != '' and Group.GroupType.TakesAttendance == 'True' %}
                {% if LinkedPages.AttendancePage == CurrentPage.Path %}
                    <li role="presentation" class="active"><a href="{{ LinkedPages.AttendancePage }}?GroupId={{ Group.Id }}">Attendance</a></li>
                {% else %}
                    <li role="presentation"><a href="{{ LinkedPages.AttendancePage }}?GroupId={{ Group.Id }}">Attendance</a></li>
                {% endif %}
            {% endif %}
            {% if AllowedActions.Edit == true %}
                {% if CurrentPage.Id == 1051 %}
                    <li role="presentation" class="active"><a href="/page/1051?GroupId={{ Group.Id }}">Group Stories</a></li>
                    {% else %}
                    <li role="presentation"><a href="/page/1051?GroupId={{ Group.Id }}">Group Stories</a></li>
                {% endif %}
                {% if CurrentPage.Id == 1054 %}
                    <li role="presentation" class="active"><a href="/page/1052?GroupId={{ Group.Id }}">Group Prayer Requests</a></li>
                    {% else %}
                    <li role="presentation"><a href="/page/1052?GroupId={{ Group.Id }}">Group Prayer Requests</a></li>
                {% endif %}
                {% if CurrentPage.Id == 625 %}
                        <li role="presentation" class="active"><a href="/page/625?GroupId={{ Group.Id }}">Group Leader Site</a></li>
                        {% else %}
                        <li role="presentation"><a href="/page/625?GroupId={{ Group.Id }}">Group Leader Site</a></li>
                {% endif %}
            {% endif %}
        </ul>
    {% endif %}
    {% if LinkedPages.RosterPage == CurrentPage.Path %}
	<div>
		<div class="arrowed">
			<div class="panel-group" id="accordion">
				{% if countPending > -1 %}
					{% assign icountPending = 0 %}
					<div class="panel panel-default">
						<div class="panel-heading">
							<h4 class="panel-title">
								<a data-toggle="collapse" data-parent="#accordion" href="#collapse1"><span class="glyphicon glyphicon-menu-right"></span> Pending Members</a>
							</h4>
						</div>
						<div id="collapse1" class="panel-collapse collapse in">
							<div class="panel-body">
								{% for member in Group.Members %}
									{% if member.GroupMemberStatus == 'Pending' %}
										{% assign loopcycle = icountPending | Modulo:2 %}
										{% if loopcycle == 0 %}
											<div class="row">
										{% endif %}
												<div class="col-sm-6 margin-b-md rollover-container" style="overflow: hidden;">
													{% if LinkedPages.PersonDetailPage %}
													<a href="{{ LinkedPages.PersonDetailPage }}?PersonId={{ member.PersonId }}">
													{% endif %}
													<img src="{{ member.Person.PhotoUrl }}&height=60&width=60&mode=crop&scale=both" height="60" class="pull-left margin-r-sm" />
													<div class="pull-left">
														<strong>{{ member.Person.FullName }}</strong>
														<small>({{ member.GroupRole.Name}})</small>
														{% if AllowedActions.Edit == true %}
															{% for phone in member.Person.PhoneNumbers %}
																<br />{% if phone.IsUnlisted != true %}<a href="tel:{{ phone.NumberFormatted }}">{{ phone.NumberFormatted }}</a>{% else %}Unlisted{% endif %}  <small>({{ phone.NumberTypeValue.Value }})</small>
															{% endfor %}
															{% assign memberAddress =  member.Person | Address:'Home' %}
															{% if memberAddress != '' %}
																<br />{{ member.Person | Address:'Home','[[Street1]] [[Street2]]<br />[[City]], [[State]] [[Zip]]' }}
															{% endif %}
															<br />
															<a href="mailto:{{ member.Person.Email }}">{{ member.Person.Email }}</a>
														{% endif %}
													</div>
													{% if AllowedActions.Edit == true %}
														<div class="pull-left rollover-item" style="position: absolute; right:0; top:0;">
															<a href="#" onclick="{{ member.Id | Postback:'DeleteGroupMember' }}" >
																<i class="fa fa-times"></i>
															</a>
															<a href="#" onclick="{{ member.Id | Postback:'EditGroupMember' }}" class="margin-l-sm">
																<i class="fa fa-pencil"></i>
															</a>
														</div>
													{% endif %}
													{% if LinkedPages.PersonDetailPage  %}
														</a>
													{% endif %}
												</div>
										{% if loopcycle != 0 or icountPending == countPending %}
											</div>
										{% endif %}
										{% assign icountPending = icountPending | Plus: 1 %}
									{% endif %}
								{% endfor %}
							</div>
						</div>
					</div>
				{% endif %}
				{% if countActive > -1 %}
					{% assign icountActive = 0 %}
					<div class="panel panel-default">
						<div class="panel-heading">
							<h4 class="panel-title">
								<a data-toggle="collapse" data-parent="#accordion" href="#collapse2"><span class="glyphicon glyphicon-menu-right"></span> Active Members</a>
							</h4>
						</div>
						<div id="collapse2" class="panel-collapse collapse in">
							<div class="panel-body">
								{% for member in Group.Members %}
									{% if member.GroupMemberStatus == 'Active' %}
										{% assign loopcycle = icountActive | Modulo:2 %}
										{% if loopcycle == 0 %}
											<div class="row">
										{% endif %}
												<div class="col-sm-6 margin-b-md rollover-container" style="overflow: hidden;">
													{% if LinkedPages.PersonDetailPage %}
														<a href="{{ LinkedPages.PersonDetailPage }}?PersonId={{ member.PersonId }}">
													{% endif %}
													<img src="{{ member.Person.PhotoUrl }}&height=60&width=60&mode=crop&scale=both" height="60" class="pull-left margin-r-sm" />
													<div class="pull-left">
														<strong>{{ member.Person.FullName }}</strong>
														<small>({{ member.GroupRole.Name}})</small></a>
														{% if AllowedActions.Edit == true %}
														    <br />Birthday: {{ member.Person.BirthDate | Date: 'sd'}}
															{% for phone in member.Person.PhoneNumbers %}
																<br />{% if phone.IsUnlisted != true %}<a href="tel:{{ phone.NumberFormatted }}">{{ phone.NumberFormatted }}{% else %}Unlisted{% endif %}  <small>({{ phone.NumberTypeValue.Value }})</small>
															{% endfor %}
															{% assign memberAddress =  member.Person | Address:'Home' %}
															{% if memberAddress != '' %}
																<br />{{ member.Person | Address:'Home','[[Street1]] [[Street2]]<br />[[City]], [[State]] [[Zip]]' }}
															{% endif %}
															<br />
															<a href="mailto:{{ member.Person.Email }}">{{ member.Person.Email }}</a>
														{% endif %}
													</div>
													{% if AllowedActions.Edit == true %}
														<div class="pull-left rollover-item" style="position: absolute; right:0; top:0;">
															<a href="#" onclick="{{ member.Id | Postback:'DeleteGroupMember' }}" >
																<i class="fa fa-times"></i>
															</a>
															<a href="#" onclick="{{ member.Id | Postback:'EditGroupMember' }}" class="margin-l-sm">
																<i class="fa fa-pencil"></i>
															</a>
														</div>
													{% endif %}
													{% if LinkedPages.PersonDetailPage %}
														</a>
													{% endif %}
												</div>
										{% if loopcycle != 0 or icountActive == countActive %}
											</div>
										{% endif %}
										{% assign icountActive = icountActive | Plus: 1 %}
									{% endif %}
								{% endfor %}
							</div>
						</div>
					</div>
				{% endif %}
				{% if countInactive > -1 %}
					{% assign icountInactive = 0 %}
					<div class="panel panel-default">
						<div class="panel-heading">
							<h4 class="panel-title">
								<a data-toggle="collapse" data-parent="#accordion" href="#collapse3"><span class="glyphicon glyphicon-menu-right"></span> Inactive Members</a>
							</h4>
						</div>
						<div id="collapse3" class="panel-collapse collapse">
							<div class="panel-body">
								{% for member in Group.Members %}
									{% if member.GroupMemberStatus == 'Inactive' %}
										{% assign loopcycle = icountInactive | Modulo:2 %}
										{% if loopcycle == 0 %}
											<div class="row">
										{% endif %}
												<div class="col-sm-6 margin-b-md rollover-container" style="overflow: hidden;">
													{% if LinkedPages.PersonDetailPage %}
														<a href="{{ LinkedPages.PersonDetailPage }}?PersonId={{ member.PersonId }}">
													{% endif %}
													<img src="{{ member.Person.PhotoUrl }}&height=60&width=60&mode=crop&scale=both" height="60" class="pull-left margin-r-sm" />
													<div class="pull-left">
														<strong>{{ member.Person.FullName }}</strong>
														<small>({{ member.GroupRole.Name}})</small>
														{% if AllowedActions.Edit == true %}
															{% for phone in member.Person.PhoneNumbers %}
																<br />{% if phone.IsUnlisted != true %}<a href="tel:{{ phone.NumberFormatted }}">{{ phone.NumberFormatted }}</a>{% else %}Unlisted{% endif %}  <small>({{ phone.NumberTypeValue.Value }})</small>
															{% endfor %}
															{% assign memberAddress =  member.Person | Address:'Home' %}
															{% if memberAddress != '' %}
																<br />{{ member.Person | Address:'Home','[[Street1]] [[Street2]]<br />[[City]], [[State]] [[Zip]]' }}
															{% endif %}
															<br />
															<a href="mailto:{{ member.Person.Email }}">{{ member.Person.Email }}</a>
														{% endif %}
													</div>
													{% if AllowedActions.Edit == true %}
														<div class="pull-left rollover-item" style="position: absolute; right:0; top:0;">
															<a href="#" onclick="{{ member.Id | Postback:'DeleteGroupMember' }}" >
																<i class="fa fa-times"></i>
															</a>
															<a href="#" onclick="{{ member.Id | Postback:'EditGroupMember' }}" class="margin-l-sm">
																<i class="fa fa-pencil"></i>
															</a>
														</div>
													{% endif %}
													{% if LinkedPages.PersonDetailPage %}
														</a>
													{% endif %}
												</div>
										{% if loopcycle != 0 or icountInactive == countInactive %}
											</div>
										{% endif %}
										{% assign icountInactive = icountInactive | Plus: 1 %}
									{% endif %}
								{% endfor %}
							</div>
						</div>
					</div>
				{% endif %}
			</div>
		</div>
	</div>
    <div class="pull-right margin-b-md">
        {% if AllowedActions.Edit == true %}
			<a href="#" onclick="{{ '' | Postback:'AddGroupMember' }}" class="btn btn-default btn-xs">
                <i class="fa fa-plus"></i> Add Member
            </a> 
        {% endif %}
        {% if LinkedPages.CommunicationPage != '' and AllowedActions.Edit == true %}
            <a href="#" onclick="{{ '' | Postback:'SendCommunication' }}" class="btn btn-default btn-xs">
                <i class="fa fa-envelope-o"></i> Email Roster
            </a>
        {% endif %}
    </div>
{% endif %}
{% else %}
    {% if Group.Id %}
        <div class='alert alert-warning'>You do not have permission to view this group.</div>
    {% endif %}
{% endif %}

Thanks again to Michael Allen and Morgan Woods for helping and inspring me to keep pushing boundaries!