Why

When our organization wanted to move all our volunteer scheduling from PCO to Rock, we knew it would be vital to give ministry Pastors the ability to customize emails. These emails would be for their ministry at their campus before sending out their group scheduling notifications. 

Giving ministry Pastors the ability to customize their emails gives each of them a voice in their emails instead of just a canned response. It also lets them inform their volunteers about exciting news, training videos, or what to expect this weekend without needing to reach out to anyone with administrative rights to change and update the email content.

Implementation

Our implementation of customizable emails takes advantage of merging in a content channel item, the ministry, and the campus through a couple of Lava Shortcodes. The parent Shortcode is present in a System Communication that is sent through the Core Rock means of Group Scheduling. We then give the ministry Pastors a comfortable interface to search for, adding, editing, and deleting emails. This interface also empowers the Pastors to see which email is live and sent upon scheduling their volunteers.

To keep this recipe relatively short, I stripped most of the styling out of the code I am sharing.

Step #1 - Add Content Channel Type 

  1. Add new content channel type with the settings below
    NewContentType2.png
  2. Add Campus Attribute that is Active, Show in Grid, and the Filter Campus Types and Status that is appropriate for your organization.ContentTypeCampus3.png

Step #2 - Add Content Channel

  • You will want to add a new Content Channel for each ministry you plan on using group scheduling for. Here are the settings we use:NewContentChannel_2.png

Step #3 - Add Default Content Channel Item

  • Adding a default item in the Content Channel you created in Step #2 is a must so that if a Pastor doesn't add one themselves, this system will have a fallback email.

Step #4 - Add Group Scheduling Active Item Lava Shortcode

  1. Add a new Lava Shortcode with these settings:
    GroupSchedlingActiveItemTop_3.png
  2. Add this code to the Shortcode Markup:
  3. {%- capture ignore -%}
    
            {% assign activeondate = activeondate | WithFallback:'','' %}
            {% assign title = title | WithFallback:'','' %}
            {% assign campusguid = campusguid | WithFallback:'','' %}
            
            
            {%- sql Title:'{{ title }}' Activeondate:'{{ activeondate }}' ParamCampus:'{{ campusguid }}'-%}
            
            Set @Title = Case when @Title = '' then null else @Title End;
            Set @ActiveOnDate = Case when @ActiveOnDate = '' then null else @ActiveOnDate End;
            Set @ParamCampus = Case when @ParamCampus = '' then null else @ParamCampus End;
            
            Declare @ContentChannelId int = {{ 'Global' | Page:'Id' | FromCache:'Page' | Attribute:'ContentChannel','Id' | Default:channelid | AsInteger | Default:'null' }}
            
            Declare @AttIdCampus        int = 8798 
                --Campus Content Item Attribute Id that was set on the content type
            
            Select
                cci.Title
                , cci.Priority
                , cci.StartDateTime
                , cci.ExpireDateTime
                , cci.Id
                , IsNull( cCampus.Name, 'All' ) as [Campus]
                , @Title as [TitleFilter]
                , @ActiveOnDate as [ActiveOnDateFilter]
            From [ContentChannelItem] cci
                Left Join [AttributeValue] avCampus
                    on avCampus.EntityId = cci.Id
                    and avCampus.AttributeId = @AttIdCampus
                Left Join [Campus] cCampus
                    on cCampus.Guid = avCampus.Value
            
                    
            Where cci.ContentChannelId = @ContentChannelId
                and ( -- Param is not defined
                    @ActiveOnDate is null
                    or (
                        -- or param matches
                        (
                            -- StartDate undefined, or before ActiveOnDate
                            cci.StartDateTime is null
                            or Convert( Date, cci.StartDateTime ) <= @ActiveOnDate 
                        ) and (
                            -- ExpireDate undefined, or before ActiveOnDate
                            cci.ExpireDateTime is null
                            or @ActiveOnDate <= Convert( Date, cci.ExpireDatetime )
                        )
                    )
                ) and (
                    @Title is null
                    or cci.Title like Concat( '%', @Title, '%' )
                ) and (
                    @ParamCampus is null
                    or @ParamCampus = avCampus.Value
                    or IsNull( avCampus.Value, '' ) = ''
                )
            Order by
                cci.Priority desc
                , cci.StartDatetime desc
                , cci.Id desc
            {% endsql %}
            
            {%- endcapture -%}
            {{- results | First | Property:'Id' -}}
  4.  Add the following Parameters and Enable the Sql Lava Command:
    GroupSchedlingActiveItemBottom_2.png

Step #5 - Add Group Scheduling Confirmation Email Content Lava Shortcode

  1. Add a new Lava Shortcode with these settings:
    GroupScheduling_ConfirmationEmail_ContentTop.png
  2. Add this code to the Shortcode Markup:
    {% assign paramcampusguid = campusguid | WithFallback:'','' %}
                {% assign paramchannelid = channelid | WithFallback:'','' %}
                {% assign paramcontentitemid = contentitemid | WithFallback:'','' %}
                
                {% if paramcampusguid == '' %}
                    {% assign paramcampusguid = Attendance.CampusId | FromCache:'Campus' | Property:'Guid' %}
                {% endif %}
                
                {% capture itemId -%} {[ groupscheduleitem channelid:'{{ paramchannelid }}' campusguid:'{{ paramcampusguid }}' ]} {%- endcapture %}
                {% assign paramcontentitemid = paramcontentitemid | WithFallback:'','' | Default:itemId %}
                
                
                {%- if paramcontentitemid == '' -%}
                There was an issue generating this email template
                
    {%- endif -%} {% contentchannelitem id:'{{ paramcontentitemid }}' %} {%- assign channelItem = contentchannelitem -%} {% endcontentchannelitem %}

    Scheduling Confirmation

    Hi {{ Attendance.PersonAlias.Person.NickName }}!

    You have been added to the schedule for the following dates and times.

    {% cache key:'SchedulingRequestContent-Channel-{{ channelid }}-Campus-{{ paramcampusguid }}-{{ contentitemid }}' tags:'groupscheduling-notifications' duration:'5' %} {{- channelItem.Content -}} {% endcache %}

    Thanks!

    {{ Attendance.ScheduledByPersonAlias.Person.FullName }}
    {{ 'Global' | Attribute:'OrganizationName' }} {% for attendance in Attendances %} {% if forloop.last %} {% endif %} {% endfor %}
     

    {{ attendance.Occurrence.Group.Campus.Name }} - {{ attendance.Occurrence.Group.Name }}
    {{ attendance.Occurrence.OccurrenceDate | Date:'dddd, MMMM d'}} - {{ attendance.Occurrence.Schedule.StartTimeOfDay | Date:'h:mm tt' }}

    {% if forloop.length == 1 %} Accept  Decline {% else %} Click to Respond {% endif %}
     
  3.  Add the following Parameters and Enable the Cache, RockEntity, & WorkflowActivate Lava Command:
    GroupScheduling_ConfirmationEmail_ContentBottom.png

Step #6 - Add New System Communication

  1.  Add a new system communication with the following settings
    SystemCommunication.png
  2. If you click the preview button you will see that your scheduling email is set up. 

Step #7 - Add a Group Scheduling Page

  1. Your next step is to create a page for your ministry leaders to view and edit the templates they want. For the sake of simplicity I put this under the intranet, but feel free to place this wherever makes sense for your organization.
    GroupSchedulingPage.png
  2. Set up security rules for this page that makes sense for your organization.  When setting the security permissions for this page, remember that its intended for ministry leaders to view.
  3. Now that we have a beautiful blank group scheduling page, we are going to create a child page of that called "Schedule Confirmation Email Edit" as seen in the next screenshot:
    EmailEdit.png
  4. With this newly created page, you'll probably just want to inherit the same security from its parent.
  5. On the "Schedule Confirmation Email Edit" page you really only need one page block and that is a Content Item Detail with the following settings:
    ContentItemDetail.png
  6. Navigating back to the "Group Scheduling Emails" page, you will need 3 different page blocks. The first page block that I placed in SectionE of that page is a "Page Parameter Filter" block with these settings:
    Filter.png
  7. In that filters block, you will need 3 different attributes those attributes need the following settings:
    FilterTitleAttribute.png
    FilterDateAttribute.png
    FilterCampus.png
  8. The last block you'll need on SectionE is a Dynamic Data block with these settings:
    DynamicData2.png
  9. Parameters:
  10. ActiveOnDate=,Title=,Campus=

  11. Query:
  12. {%- assign paramCampus = 'Global' | PageParameter:'Campus' -%}
    
    
            -- Handle Blank case from Block Parameterization
            Set @Title = Case when @Title = '' then null else @Title End;
            Set @ActiveOnDate = Case when @ActiveOnDate = '' then null else @ActiveOnDate End;
            
            Declare @CurrentPageRoute varchar(max) = '{{ "Global" | Page:"Url" | Split:"?" | First | SanitizeSql }}'
            
            Declare @ContentChannelId int = 8
                --Content Channel Id that was set on the content channel
            Declare @ParamCampus varchar(max) = '{{ paramCampus }}'
            Set @ParamCampus = Case When @ParamCampus = '' Then null Else @ParamCampus End
            
            Declare @AttIdCampus        int = 7392
                --Campus Content Item Attribute Id that was set on the content type
            
            Select
                cci.Title
                , cci.Priority
                , cci.StartDateTime
                , cci.ExpireDateTime
                , cci.Id
                , @CurrentPageRoute as [CurrentPageRoute]
                , @ParamCampus as [ParamCampus]
                , IsNull( cCampus.Name, 'All' ) as [Campus]
                , IsNull( cCampus.Guid, null ) as [CampusGuid]
                , @Title as [TitleFilter]
                , @ActiveOnDate as [ActiveOnDateFilter]
            From [ContentChannelItem] cci
                Left Join [AttributeValue] avCampus
                    on avCampus.EntityId = cci.Id
                    and avCampus.AttributeId = @AttIdCampus
                Left Join [Campus] cCampus
                    on cCampus.Guid =  avCampus.Value 
                    
            Where cci.ContentChannelId = @ContentChannelId
                and ( -- Param is not defined
                    @ActiveOnDate is null
                    or (
                        -- or param matches
                        (
                            -- StartDate undefined, or before ActiveOnDate
                            cci.StartDateTime is null
                            or Convert( Date, cci.StartDateTime ) <= @ActiveOnDate 
                        ) and (
                            -- ExpireDate undefined, or before ActiveOnDate
                            cci.ExpireDateTime is null
                            or @ActiveOnDate <= Convert( Date, cci.ExpireDatetime )
                        )
                    )
                ) and (
                    @Title is null
                    or cci.Title like Concat( '%', @Title, '%' )
                ) and (
                    @ParamCampus is null
                    or @ParamCampus = avCampus.Value 
                    or IsNull( avCampus.Value, '' ) = ''
                )
            Order by
                cci.Priority desc
                , cci.StartDatetime desc
                , cci.Id desc
  13. Hidden Columns:
  14. Id,TitleFilter,ActiveOnDateFilter,CurrentPageRoute,CampusGuid,ParamCampus

  15. Selection Url:
  16. {CurrentPageRoute}?ItemId={Id}&Title={TitleFilter}&ActiveOnDate={ActiveOnDateFilter}&CampusGuid={CampusGuid}&Campus={ParamCampus}

  17. In the Dynamic Data Block's Advanced Settings Add the folling code to the Pre-HTML:
  18. {%- assign newTemplateUrl = 2688 | PageRoute:'ContentItemId=0' -%} {% comment %}Change this Id to the Id of the child of
            this page{% endcomment %}
            
            

    LifeKids - Schedule

    Add New Template
  19. In the Dynamic Data Block's Advanced Settings Add the folling code to the Post-HTML:
  20.