I recently rebuilt our website from scratch using Rock. I ended up relying pretty heavily on Content Components to allow other staff members to easily update their content without compromising the structure and design. Toward the end of the project, I started noticing that there were times when I needed to make updates to the functionality of a Content Component, but I couldn't quite remember every place I had used the component to make sure that my changes didn't break an existing page.

As a solution, I wrote a SQL query to show exactly which pages/blocks included each of our Content Component Templates. This recipe takes that query and creates a new filterable report page. It also adds links on the existing Content Component Templates page for each of the templates records that takes you directly to a filtered version of the report page for the selected template.

How To

  1. Create a new page under Internal Homepage > Admin Tools > Rock Settings > CMS Configuration
    • Page Title: Content Component Finder
    • Site: Rock RMS
    • Layout: Full Width
    • Icon CSS Class: fa fa-search-location
  2. Make a note of the ID of your new report page for later
  3. Add a new Page Parameter Filter block to the Main zone
    • Block Title: Filters
    • Show Block Title: Yes
    • Block Title Icon CSS Class: fa fa-filter
    • Filter Button Text: Apply Filter
    • Show Reset Filters Button: Yes
    • Filters Per Row: 2
    • Does Selection Cause Postback: Yes
    • Filters:
      • Content Component Template
        • Name: Content Component Template
        • Key: Template
        • Field Type: Defined Value
        • Defined Type: Content Component Template
        • Allow Multiple Values: No
        • Include Inactive: Yes
        • Allow Adding New Values: No
      • Site
        • Name: Site
        • Key: Site
        • Field Type: Site
        • Shortening Enabled Sites Only: No
  4. Save the Page Parameter Filter block
  5. Add a Dynamic Data block to the Main zone
    • Block > Block Properties > Advanced:
      • Pre-HTML:
        <div class="panel panel-block">
            <div class="panel-heading">
                <h3 class="panel-title"><i class="fa fa-sitemap"></i> Content Component Template References</h3>
            <div class="panel-body">
      • Post-HTML:
      • Paneled Grid: Yes
    • Block > Edit Criteria:
      • SQL Query:
        DECLARE @SiteID AS int = {{ 'Global' | PageParameter:'Site' | Default:'NULL' }}
        {%- assign templateGUID = 'Global' | PageParameter:'Template' | Default:'' -%}
        {%- if templateGUID != '' -%}
        DECLARE @TemplateGUID AS uniqueidentifier = CAST('{{ templateGUID }}' AS uniqueidentifier)
        {%- else -%}
        DECLARE @TemplateGUID AS uniqueidentifier = NULL
        {%- endif -%}
        DECLARE @TypeGUID AS uniqueidentifier = CAST('313b579f-f442-4247-adbb-bbd25e255003' AS uniqueidentifier) --make sure this GUID matches your Content Component Template defined type
        DECLARE @AttributeGUID AS uniqueidentifier = CAST('f33c44c4-615e-4254-9a97-9dd1d9922c32' AS uniqueidentifier) --make sure this GUID matches the Content Component Template attribute for the defined type
        DECLARE @AttributeID AS int
        DECLARE @TypeID AS int
        SELECT @AttributeID = ID FROM Attribute WHERE GUID = @AttributeGUID
        SELECT @TypeID = ID FROM DefinedType WHERE GUID = @TypeGUID
        SELECT DV.ID AS TemplateID, L.SiteID, B.PageID, DV.Value AS Template, 
            ISNULL(S.Name, '–') AS Site, 
            ISNULL(P.PageTitle, '–') 
                + CASE WHEN P.ID IS NOT NULL AND S.ID IS NULL THEN  '  Orphaned Page' ELSE '' END AS Page, 
            ISNULL(B.Name, ' Never Used') 
                + CASE WHEN B.ID IS NOT NULL AND P.ID IS NULL THEN '  Orphaned Block' ELSE '' END AS Block
        FROM DefinedValue DV LEFT JOIN
            AttributeValue AV ON AV.Value = CAST(DV.GUID AS varchar(36)) AND AV.AttributeID = @AttributeID LEFT JOIN
            Block B ON B.ID = AV.EntityID LEFT JOIN
            Page P ON P.ID = B.PageID LEFT JOIN
            Layout L ON L.ID = P.LayoutID LEFT JOIN
            Site S ON S.ID = L.SiteID
        WHERE DV.DefinedTypeID = @TypeID
            AND (DV.GUID = @TemplateGUID OR @TemplateGUID IS NULL)
            AND (S.ID = @SiteID OR @SiteID IS NULL)
        ORDER BY DV.[Order], DV.Value, S.Name, P.PageTitle
      • Hide Columns: TemplateID,SiteID,PageID
      • Selection URL: /page/103?Page={PageID} Make sure this matches the ID of your Pages page
      • Person Report: No
      • Show Grid Actions: Excel Export
      • Show Grid Filter: No
  6. Save the Dynamic Data block
  7. Switch to the Content Component Templates page at Internal Homepage > Admin Tools > Rock Settings > CMS Configuration > Content Component Templates
  8. Open the Block Properties for the Content Component Template List (Defined Value List) block and go to the Custom Grid Options tab
  9. Under Custom Columns, add a new column
    • Column Position: Last Column
    • Offset: 1
    • Header Text: blank
    • Header Class: grid-columncommand
    • Item Class: grid-columncommand
    • Lava Template:
      {% if Row.Id > 0 %}
          <a title="Find all occurrences of this template" href="/Page/YOUR_REPORT_PAGE_ID?Template={{ Row.Guid }}" target="_blank" class="btn btn-default"><i class="fa fa-sitemap"></i></a>
      {% endif %}

      Make sure to replace YOUR_REPORT_PAGE_ID with the ID of your new report page.

  10. Save the Block Properties and you're done!

There will be a new button to the right of every template on the Content Component Templates page that will take you to a list of every site, page and block that references the template.

Alternatively, you can go directly to the Content Component Finder page by going to Admin Tools > CMS Configuration > Content Component Finder. By default the page will show references for every template on every site in Rock. Column headers can be clicked to re-sort the references or the Filters panel can be used to narrow the list down to only certain templates or sites.

Please leave a comment or hit me up on Rock Chat if you have questions or find any issues with this recipe. Thanks!