Tuesday, July 27, 2021

"Gracious and Holy"

Over the past month, the Student Pastor at our church (and a dear friend) Evan Smith has been filling the pulpit on Sunday mornings as our senior pastor enjoys some much-deserved vacation time. (You might have noticed, but 2020 was a rather hard year for folks, and perhaps especially pastors.) Evan chose to deliver a cohesive, four-part sermon series, and settled a couple of months ago on the theme of God's presence. Over the four weeks, he planned to illuminate the thread of God's desire to dwell with His people that runs through the whole of Scripture: from Eden (where God walked with Adam and Eve), through the Exodus (where God "tabernacled" with the Israelites), to the Embodiment (or Incarnation, where Jesus — the Word who both was with God and was God — became flesh and dwelt among us), and into the promise of Eternity (where the people of God will enjoy the immediate presence of God forever). And if you were paying close attention, you noticed that those four waypoints were alliterative — such a good Baptist pastor! But between the lines of this story runs the equally deep and powerful truth of God's nature as both perfectly holy — such that imperfection in His presence runs the risk of eradication — and immensely gracious.

These were some of the many thoughts swimming around in my head on July 4, 2021. I was hiking alone the Robbins Branch Loop Trail in the Uwharrie National Forest, and trying to enjoy a calmness of mind. Irritatingly, though, my brain just seemed frantic — jumping from thought to thought across all the various roles I play (husband, parent, employee, worship leader, etc.). At one point, I actually yelled aloud in the forest in frustration, "Why is it so noisy in here?!" And then a strange thing happened. In what seemed like no time at all, the melody and opening words of the chorus of a new song were in my head, coalescing around the themes of Evan's sermon series. I spent the next several hours (and about 8 miles of hiking) developing the skeleton of the song. I was super-grateful to be alone in the woods, not least because it's really embarrassing to be tripping over tree roots whenever I turned my attention to my phone's voice recorder app or tried to type into it some lyric ideas!

Once home, I spent the next week or so putting meat on the song skeleton. Friends I shared the concept with seemed more supportive of this song than usual, so it felt like effort well-invested. And this past Sunday, Amy and I — along with other members of our church's worship team — shared the song with our church family. God be praised for using such an unworthy vessel to encourage His Church in song. Gracious and holy He truly is.

"Gracious and Holy" You made the Earth and the heavens. Spoke words to form them and fill them. So all that we have is by Your hand. Gracious and holy You are. You gave us freedom and purpose. We chose rebellion and curses. But hope lingered under the surface. Gracious and holy You are. Gracious and holy You are. You are here, always with me, Nearer than sacred to naked should be. You speak promises over my shame. I know that I'll never be the same. You came to dwell with Your people; Strengthen the downcast and feeble; And rescue us from every evil. Gracious and holy You are. Humbly you gave Your life for us. Hope is reversing our curses, Restoring our freedom and purpose. Gracious and holy You are. Gracious and holy You are. You are here, always with me. Nearer than righteous to wretched should be. You speak promises over my shame. I know that I'll never be the same. Now you are seated in Heaven, So, by the Spirit You've given, We will proclaim, "Christ is risen!" Gracious and holy You are. Gracious and holy You are. You are here, always with me, Nearer forever than failure could be. You poured righteousness over my shame. Called me Your child and then gave me Your name. You are here, always with me, Nearer forever than failure could be. You poured righteousness over my shame. I know that I'll never be the same. I know that I'll never be the same. ©2021 C. Michael Pilato; License: CC-BY-3.0

Here also is a demo recording that I made as a reference for our worship team (with many thanks to my son Aidan for lending his percussive skills):

Finally, you can get lead sheets (including the source MuseScore file) for the song from my GitHub repository.

Wednesday, March 3, 2021

My custom Planning Center Services plan report. You're welcome.

To all my fellow Planning Center Services jockeys out there, I thought I'd share with you a custom Plan report that I created (using one of the built-in reports as a baseline, mind you) and have been using for years now. Now, before you assume that all I've done here is fiddle with colors and fonts and page layout, hear me out. There are some features of this template that I want you to know about.

First—and the primary reason that I love this template so much—is that it handles Plan and Item Note categories dynamically. Unlike the built-in templates, this report template doesn't have to be modified just because you use different Notes categories than the default Planning Center ones. In fact, it doesn't care what specific Notes categories you have at all. Rather, it examines the Plan and its Items and dynamically determines which Note types are actually employed. This means two things: that it doesn't waste any page/screen real estate on unused Note categories, and you can use the same template for entirely different Service Types with entirely different categories defined!

The second, admittedly minor, thing that I like about this template is that it adds a column for icons that appear next to certain Item types. So Songs show up with a music notes icon (♫) next to them; Media items show a "play" triangle (⏵). It's a little thing, but it draws the eye to certain Item types quickly.

Finally, the template itself allows some quick customization of the features it employs via a collection of boolean variables at the top.  This allows you to use the same basic template for multiple custom Reports, but with little easy tweaks to goven the feature set for each one.  So, for example, I have a Report that shows everything that I distribute to my A/V operators and band members.  But I have another one using this same template that I use for our Ushers and Greeters where the variables show_plan_people, show_plan_notes, and show_item_notes have been set to false.

So, without further ado, my template. Please feel free to copy, use, and modify this thing to better suit your church's needs!

<!-- QUICK CUSTOMIZATION: {% assign show_plan_notes = true %} {% assign show_plan_people = true %} {% assign show_item_times = true %} {% assign show_item_length = true %} {% assign show_item_description = true %} {% assign show_item_notes = true %} --> <html> <head> <title>{{ plan.ministry.name }}:: {{ plan.dates }}</title> <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,600;1,400;1,600&display=swap" rel="stylesheet"> <style> body { padding: 0; margin: 5px; color: #222; font-family: Roboto, sans-serif; font-size: 14pt; } h1 { font-size: 1.5em; font-weight: normal; text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.9); } h2 { font-size: 1.1em; font-weight: normal; padding: 20px 35px; margin: 0; line-height: 1em; text-shadow: 0 1px 0 white; } h3 { font-size: 0.9em; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); } pre { margin: 0; padding: 0; white-space: pre-wrap; font-size: .9em; } table#plan { width: 100%; border-collapse: collapse; margin-top:0px; margin-bottom: 15px; font-size: 10pt; } table#plan tr { border-bottom: 1px solid #ddd; } table#plan thead { display: table-header-group; } table#plan th { color: white; background: #444; font-weight: bold; padding: 0.5em 1em; vertical-align: middle; } table#plan td { text-align: center; padding: 0.5em 1em; } table#plan .icon { padding: 0; } table#plan .preservice .time, table#plan .preservice .length { color: #aaa; } table#plan .time { width: 3em; text-align: center; } table#plan .length { width: 3em; text-align: center; } table#plan .note_column { text-align: left; background: #f8f8f8; border-left: 2px solid white; } table#plan .header { text-align: left; font-weight: bold; color: black; background: #ddd; } table#plan .note { font-weight: bold; text-align: left; vertical-align: middle; min-width: 1in; } table#plan .element { min-width: 3in; text-align: left; } table#plan .element .description { font-size: 0.86em; color: #444; font-style: italic; } table#header { width: 100%; border: none; padding: 0; border-collapse: collapse; } table#header td { padding: 2px; vertical-align: top; } .artwork { float: left; margin-right: 15px; height: 40px; } .note_content { background: yellow; padding: 4px 8px 0; border-radius: 0.3em; } #header { padding: 5px 20px; background: #000; color: white; line-height: .8em; margin: 0; } #header img { float: right; height: 60px; margin-right: -15px; } #titles { color: #333; font-size: 1.1em; font-weight: normal; padding: 10px 20px; margin: 0; line-height: 1.1em; text-shadow: 0 1px 0 white; min-height: 45px; } #plan_title { font-style: normal; font-size: 0.8em; display: block; color: #666; margin: 4px 0 0 0; } #plan_notes, #plan_people { background: #f8f8f8; margin: 1em 0; border-left: 4px solid black; padding: 0.5em 0 1em 2em; } #plan_notes { font-size: 0.8em; background: #ffffd0; } #plan_notes .plan_note { margin-top: 1em; } #plan_notes .plan_note_category { font-weight: bold; } #plan_people { font-size: 0.9em; } #plan_people .person { font-size: 0.7em; margin-right: 15px; display: inline-block; } #plan_people .person_status_U { opacity: 0.5; } #plan_people .person_category { clear: both; padding-top: 1em; } #plan_people .person_category p { font-size: 0.8em; margin: 0; } #plan_people .person_position { font-style: italic; } #plan_people .position { font-weight: bold; } </style> </head> <body> <!-- If showing item notes, first build a list of item note categories in use. --> {% if show_item_notes %} {% assign used_item_note_categories = '' | split: '' %} {% for item in plan.items %} {% for note in item.notes %} {% assign category = note.category.name | split: '|' %} {% assign used_item_note_categories = used_item_note_categories | concat: category %} {% endfor %} {% endfor %} {% assign used_item_note_categories = used_item_note_categories | uniq | sort %} {% endif %} <div id="header"> <h1>{{ plan.ministry.name }} - {{ plan.dates }}</h1> </div> <div id="titles"> <img class="artwork" onerror="this.style.display='none'" src="{{ plan.series_artwork_url }}" /> <div id="series_title">{{ plan.series_title }}</div> <div id="plan_title">{{ plan.plan_title }}</div> </div> <!-- If showing plan notes, first build a list of plan note categories in use, then iterate. --> {% if show_plan_notes %} {% assign used_plan_note_categories = '' | split: '' %} {% for note in plan.notes %} {% assign category = note.category.name | split: '|' %} {% assign used_plan_note_categories = used_plan_note_categories | concat: category %} {% endfor %} {% assign used_plan_note_categories = used_plan_note_categories | uniq | sort %} {% unless used_plan_note_categories == empty %} <div id="plan_notes"> {% for plan_note_category in used_plan_note_categories %} <div class="plan_note"> <div class="plan_note_category">{{plan_note_category}}</div> {% for note in plan.notes %} {% if note.category_name == plan_note_category %} <div>{{note.note}}</div> {% endif %} {% endfor %} </div> {% endfor %} </div> {% endunless %} {% endif %} <table id="plan"> <thead> <tr> {% if show_item_times %} {% for time in plan.plan_times %} <th class="time">@{{ time.starts_at | date: '%I:%M' }}</th> <!-- {% increment colspan %} --> {% endfor %} {% endif %} <th class="icon"></th> <!-- {% increment colspan %} --> <th align="left">Element</th> <!-- {% increment colspan %} --> {% if show_item_notes %} {% for category in used_item_note_categories %} <th class="note">{{ category }}</th> <!-- {% increment colspan %} --> {% endfor %} {% endif %} {% if show_item_length %} <th class="length">Length</th> <!-- {% increment colspan %} --> {% endif %} </tr> </thead> <tbody> {% for item in plan.items %} {% case item.item_type %} {% when 'Header' %} <!-- Header rows --> <tr> <td colspan="{{ colspan }}" class="header">{{ item.title }}</td> </tr> {% else %} <!-- Non-header rows --> {% assign item_class = ''%} {% if item.is_preservice or item.is_postservice %} {% assign item_class = 'preservice ' %} {% endif %} <tr class="{{ item_class }}"> {% if show_item_times %} {% for time in plan.plan_times %} <td class="time item {{ item_class }} {{ item.item_type }}"> {% for item_time in item.times %} {% if item_time.time_id == time.id %} {{ item_time.actual_time | date: '%I:%M' | downcase }} {% endif %} {% endfor %} </td> {% endfor %} {% endif %} <td class="item icon"> {% if item.item_type == "Song" %}&#9835;{% endif %} {% if item.item_type == "Media" %}&#9205;{% endif %} </td> <td class="item element {{ item_class }} {{ item.item_type }}"> {{ item.title }}{% if item.song %} [{{ item.arrangement.music_key }}]{% endif %} {% if show_item_description %}<div class="description">{{ item.description }}</div>{% endif %} </td> {% if show_item_notes %} {% for category in used_item_note_categories %} <td class="item note note_column {{ item_class }} {{ item.item_type }}"> {% for note in item.notes %} {% if note.category_name == category %} {{ note.note }} {% endif %} {% endfor %} </td> {% endfor %} {% endif %} {% if show_item_length %} <td class="item length {{ item_class }} {{ item.item_type }}">{{ item.length }}</td> {% endif %} </tr> {% endcase %} {% endfor %} </tbody> </table> {% if show_plan_people %} <!-- If showing plan people, first build a list of person categories in use, then iterate. --> {% assign used_person_categories = '' | split: '' %} {% for plan_person in plan.plan_people_not_declined %} {% assign category = plan_person.category.name | split: '|' %} {% assign used_person_categories = used_person_categories | concat: category %} {% endfor %} {% assign used_person_categories = used_person_categories | uniq | sort %} {% unless used_person_categories == empty %} <div id="plan_people"> {% for plan_person_category in used_person_categories %} <div class="person_category"> <p><strong>{{ plan_person_category }}</strong></p> {% for plan_person in plan.plan_people_not_declined %} {% if plan_person.person.name != null %}{% if plan_person.category.name == plan_person_category %} <div class="person person_status_{{ plan_person.status }}"> &bull; <span class="person_name">{{ plan_person.person.name }}</span> <span class="person_position">({{ plan_person.position }})</span> </div> {% endif %}{% endif %} {% endfor %} </div> {% endfor %} </div> {% endunless %} {% endif %} </body> </html>

As of a few minutes ago, I've submitted this report template back to the fine folks that develop Planning Center Services so that they may consider integrating its enhancements into the core product itself.