Saturday, November 18, 2017

Thank You Community Leaders 2017

In the season of Thanksgiving, it felt appropriate to share some appreciation for members of the community. This list is by no means a complete and thorough account of what I received but it's a good start.

Akshay Sura

Akshay is a friend to everyone. Some of my favorite shirts were gifts from him. He's the reason we have http://www.ourcorecommunity.com/ and the much needed "Unofficial Sitecore Training". It's no wonder he received the most community votes for the "Core Community Friend Award 2018". Thank you Akshay for all you do for me and the community. Without you there would be a huge hole in the TEAM. Reach him on Slack as @akshaysura.



Kamruz Jaman

Lieutenant Troll and one of the best Sitecore Technical Support members on Slack. Kidding aside, he has helped so much through his blog posts and insights while communicating on the Sitecore Slack Chat. The Core Community Award was a big hit with your help. Overall funny guy and easy to get along with. Thank you Kamruz for all you do for me and the community. Without you the bridge would be a lonely place. Reach him on Slack as @jammykam.

Kam Figy

Thank you for your strangely named open source products like Unicorn, Rainbow, Dianoga, and Pickled Feet Beaver. Unicorn has been a huge time and money saver. Thank you Kam for being the super smart guy we all need. Reach him on Slack as @kamsar.


Mark Cassidy

Thank you for possessing the grit needed to keep the Sitecore Stack Exchange alive. IIRC you stated this was the third try and so far it's a huge success. There is so much we've gained by having a Stack Exchange. Looking forward to our next root beer! Reach him on Slack as @cassidydotdk.

Adam Najmanowicz

Thank you for being foolish enough to let me help with SPE and leaving all the book documentation to me :) Your help with Zen Garden and now SXA has been fantastic.You nominating me for my first MVP award has made all the difference in my participation within the Sitecore community. Thank you Adam for telling me "no" when my ideas are crazy and "yes" when you're tired of arguing. Looking forward to our next root beer....well I'll drink the root beer since you think it tastes like toothpaste. Reach him on Slack as @adamnaj.


Honorable Mentions

Thank you Mike Reynolds for the copious amounts of blogging you did that help me get a jump start on Sitecore development. The Core Community Award was a big hit with your help as was the "Unofficial Sitecore Training". Also, thank you for nominating me for my first MVP award; look how much I've grown! Reach him on Slack as @sitecorejunkie.

Thank you Una Verhoeven for all your Sitecore community work and helping me with SXA. Your help made my first implementation that much better. Reach her on Slack as @una.verhoeven.

Final Thoughts
I encourage you to show your appreciation for those that have really helped you. Consider recommending those same people for Sitecore MVP. Also, try not to DM those people on Slack for support; stick to the group channels and only shift to the DM when they invite you to do so.

Friday, November 17, 2017

Improve the Experience for Designers in SXA with Styles

Recently I saw a nice article by Barend Emmerzaal proposing a way to improve the Experience Editor when using SXA. The article reminded me of an improvement the team and I made when rolling out a website on SXA. The problem I wanted to solve revolved around the search components and their default behavior.

Overview

Here's a brief overview of a few scenarios I may be able to address for you in this article:

  • The Search Results component displays results automatically. How do you hide the results when a user has not yet performed an explicit search, such as with an address using the Location Finder component (Location Aware) or free text with Search Box component (Query Aware)?
  • The Rich Text component can be used to display a message to the user until an explicit search is performed. How do you hide the message after a search is performed?
  • The component is hidden when the page loads for the user, but the Designer needs to see it in the Experience Editor. How do you signal to the user which components are Search [Query|Location] Aware?
The approach I've taken requires a few steps:

  1. Add SXA-supported styles to components that should be hidden/shown when certain conditions are met.
  2. Add JavaScript to toggle visibility for components that should be shown/hidden after specific conditions are met.
Note: Screenshots are taken from an instance of Sitecore running XA.Reference

Final Result

Let's have a look at the final results in the Experience Editor. If you are still interested afterwards, keep on reading.

Example with hidden Search Results


The Search Results component is currently hidden in the left column. Here's how that looks in the Experience Editor. The component is part of a Partial Design, which explains why no other component is seen.

Style "Show If Query" indicated on Search Result component
Search Box visible on Page


The "Show If Query" indicates that a style is applied to show the Search Result component when a user-provided query exists.

Getting Started

Begin by adding the stylesheet and script linked below into your theme. To keep things simple I've added the items in the Basic(2) theme; you could however separate between Editing Theme and Basic(2).

Next I've added two styles to the component, the first to make it query-aware, and the second to show when a query has been entered.

Styles added using SXA selector

You can make these new styles available by navigating to the Presentation->Styles section under your sit and using the appropriate insert options.

Style value matches Stylesheet

So how does this all work together? Let me explain:

  1. The style "search-query-aware" tells the JavaScript that it should monitor components with the class whenever the query hash changes.
  2. The style "search-query-show" tells the JavaScript that the component should be hidden on page load but made visible when the query hash is not empty.
  3. The style "search-query-true" is added and "search-query-false" is removed when the query hash is not empty. Reverse this when "search-query-hide" is used.
Now let's have a look at this in action.



All the sample code can be found here:

Sunday, June 18, 2017

SPE Workflow Action using Slack Notifications

Have you ever wondered how to notify a user about workflow changes to an item in Sitecore, but not through email? In this post I'll show you in a few steps how to send notifications to a user or channel in Slack when transitioning an item's workflow state in Sitecore.

TL;DR;

  1. Setup a Slack authentication token here. The documentation indicates there are some newer ways to acquire a token, but for now we'll go with the low effort approach.
  2. Setup the PSSlack module for PowerShell found here. Optionally, run Install-Module PSSlack from an elevated PowerShell console. Big thanks to @pscookiemonster for putting this together.
  3. Create a SPE workflow action like described here.
  4. Update the script to send messages to Slack.
  5. Celebrate!

Example Notification



Friday, April 21, 2017

Custom Rendering Variant Token Tool for SXA

Sitecore Experience Accelerator (SXA) provides a great way to alter how components render using a feature called Rendering Variant. The following post describes how I developed a new Rendering Variant tool that implements NVelocity templates. I found a way to extend a feature built into the great SXA.

For those that have not yet worked with NVelocity, it's essentially a mechanism for converting tokens into other text. This is often used in Sitecore standard values where you use $name to populate the title field.

UPDATE: SXA comes with some tools that you can take advantage of right now called $dateTool and $numberTool. Read more about them here and here.

Problem Statement

Marketing would like to have the page Url output in the website global search results.


As you can see above, the rendering shows a title, description, and url. Unfortunately  I was not able to figure out how to do this OOTB with SXA. Fortunately it took very little effort to write code for this.

Setup

There are a few steps you need to take in order for this to work.
  1. Have a need for it. Duh.
  2. Setup a Visual Studio project, something like Company.Foundation.Variants.
  3. Reference the SXA library Sitecore.XA.Foundation.Variants.Abstractions.dll, Sitecore.Kernel.dll, and Sitecore.NVelocity.dll.
  4. Add a new class to define the tool, such as Company.Foundation.Variants.NVelocityExtensions.LinkTool.
  5. Add a new class to register the tool, such as Company.Foundation.Variants.Pipelines.GetVelocityTemplateRenderers.AddTemplateRenderers.
  6. Patch the new pipeline in to getVelocityTemplateRenderers.
Here's a little snippet to get you started.

Usage

In the Rendering Variant configured for search results, add a VariantTemplate item. The template field should then contain something like the following:

<a href="$linkTool.GetItemLink($item)">$linkTool.GetItemLink($item,true)</a>

Here is the html set within the VariantTemplate.


That's pretty much all there is to setting it up. Hope you find this feature as helpful as I did!

Saturday, April 15, 2017

Unicorn Serialization for SXA Projects

Sitecore Experience Accelerator (SXA) is organized in a way that aligns with Sitecore's Helix design principles and conventions. The following post describes how I structured a solution with Unicorn serialization to allow for low complexity management.

I'll try to explain as much as I can using pictures; everyone likes pictures.

Organizational Structure

The following names will be used to organize code and serialized content.
  • Feature
  • Foundation
  • Project
  • Website


Starting from the bottom I have a project using the naming convention [COMPANY].Website. This project contains code and configurations needed to bootstrap a website that would keep it in an operational state. Changes to Sitecore.config would appear as patch-configs in this project.

Let's have a look at this node expanded.



Example:
The configuration Company.Serialization.config contains all of the root items necessary for Unicorn to work in the solution. I've sanitized the example to use the generic name Company


Now let's have a quick look at some of the places where those items are in the Sitecore tree. The company name here is Concentra.


The configuration file is designed to create all of those root items. When a new developer joins, he/she will want to sync the Company.Website configuration first so all these root nodes appear.

Example:
The configuration Company.Project.DotCom.Serialization.Dev.config contains all of the descendant items that are project specific, such as site templates. This config contains the settings necessary for TransparentSync.

When you create a new tenant and site with the SXA wizard (powered by Sitecore PowerShell Extensions!) you will want to use the structure Tenant Folder > Tenant > Site (i.e. Concentra > DotCom > usa). I like this pattern because you future-proof the structure to support multiple companies.
You will want to use this configuration on your developer machine. Everything is tracked and transparently synced.

Example:
The configuration Company.Project.DotCom.Serialization.Cm.config contains the same as before, but disables TransparentSync and uses exclusions. You will want to use this configuration on Content Management environments, the primary reason is because the Home and Data trees should not be overwritten; Marketers will want to punch you if you do.

Putting it all together

So let's recap what we have.
  • Visual studio projects for Website, Project, Foundation, and Feature.
  • Unicorn serialization configurations that capture root nodes for the company (Website) and then other configurations for the tenant and site (Project). Foundation and Feature work the same way but have no information about the tenant/site.
  • Unicorn serialization configurations take into account what developers want to capture and own versus what should be deployed to other environments.
  • Unicorn files and configurations are removed before each deployment to ensure renamed or unused files are removed.
Here's a short video to add more detail.Thanks for watching!


Sunday, October 9, 2016

Build a Location Finder search using SXA

Recently I've been playing around with the new Sitecore Experience Accelerator (SXA) and wanted to share something that is possible without any coding.

Here's a preview in case you don't want to read the rest of the post.


Isn't the kitty cute? Moving on...

SXA is bundled with quite a number of search components. Let us see what is in use.
  • Location Finder - essentially a search box with label and button.
  • Search Results - just like it sounds.
  • Filter (Radius) - used to reduce the search results by geospatial comparison.
  • Map - a map using the Google Maps JavaScript API.
When you add search components to the page, they automatically interact with one another. In the event you want to have multiple searches on the same page, change the signature property on the components.

I have no need to make the search signature unique for this page so I will leave it empty. 

Another interesting part about these components is the use of the hash parameters. In this example, I changed the distance filter to 500 miles and the data was automatically populated in the url.


In the above image, the hash query contains an entry for the geolocation (g), order (o), and distance (DistanceMi).

Let's have a look at each of the search components in greater detail.

Location Finder

This control deals with accepting search criteria from the user in the form of a city, state, or zip code.

As you enter data in the field you'll see the Google Autocomplete feature activate. Selecting the city will immediately trigger the hash query to update with the new location which in turn runs a search.

As of version 1.1 there is no out of the box way to limit the results by country or city.

Note: Before adding this component to the page you'll need to create a few settings.

Distance Facet
I created a new DistanceFacet item to specify that the filter will use the unit of miles. Add a new facet under Settings -> Facets.


Location Filter
Next I created a new LocationFilter item to be used as the data source. This item makes use of the  DistanceFacet. Go ahead and set the placeholder text, label text, and finally the button text. Add a new filter under Data -> Search -> Location Filter.


Search Results

This control is responsible for rendering the queried items. We will need an item to specify the search scope.

Scope
The Scope item uses a Sitecore query to get the appropriate data. The query needs to return items that inherit from the POI template which contains fields like Latitude and Longitude. Add a new scope under Settings -> Scopes.


I used this query to get the job done. The default scope is the entire site so be sure to do this. Further down in this post you'll see how I created the POI items returned by this query.

location:{BE88BF74-BBD1-4BB0-A4ED-1E34F477F985};+custom:_templatename|poi

While you are there make sure that the Search Results component has a default data source for use when no results are found under Data -> Search -> Search Results.



Edit the component properties to make use of the scope and default result.

Filter (Radius)

This control enhances the results by filtering our the specified radius (miles or kilometers).

Radius Filter
The Radius Filter item specifies which distance facet to use. Add it under Data -> Search -> Radius Filter.

Radius Scheme
The Radius Scheme item specifies which options are available for filtering.


Note: I was not quite sure where to place the Radius Scheme item because no insert option existed so I placed it under Data -> Search -> Radius Filter. I also didn't know the Radius Scheme existed until I dug around to see what I needed to create. Looking forward to the detailed documentation for each of this features in the near future.

Map

This control renders the search results on a map with location markers. The search results need to have the Latitude and Longitude populated for this to work properly. Be sure to create a Map item under Data -> Maps before adding this control to the page.


POI Type
The POI Type item provides a way to customize the marker icon. For this demo I created a new POI type under Presentation -> POI Types, which allowed me to specify the awesome SPE custom marker icon.


POI
The POI item as mentioned before contains the Latitude and Longitude necessary for the spatial search to function. I used the POI Group item to help organize the POI items by state. Notice that the Type field uses the custom SPE POI.

Each of the cities are represented by the base POI which comes with a title, description, and image field.

Rendering Variants
The creation of new Rendering Variants for these controls is the last piece to making this work. The following should be added or updated to meet your visual needs.

For the POI rendering variant I set the Default Variant on the custom SPE POI. This should influence the presentation of the InfoWindow that appears on the map.

For the Search Results rendering variant I created a new Location Variant and applied it in the Experience Editor for the component.

I styled the rendering variant to help position the title, description, latitude, longitude, and image into the beautiful structure seen above.

Update

After I rolled out a new website using the information in this article, I discovered that I need to use a *VariantTemplate* for the distance.


Since the template is using NVelocity, you can add some additional checks so that the markup will be empty with the distance has no value.

#if ($geospatial && $geospatial.Distance) $geospatial.Distance miles #end

Conclusion

That's pretty much all it takes to build a custom Location Finder on your website. The only code required was using SPE to siphon all of the geo data and images into Sitecore.

Additional Resources
If you haven't checked out Reinoud's post on Partial Designs and Page Designs I would highly recommend you do that today as it will give you some clue at how to build up the page in this article. Looks like there was even a refresh on the icons too!

I've chosen to use the Basic provided with SXA rather than the Wireframe theme so all my images show up.

Monday, July 13, 2015

Sitecore PowerShell Extensions Remoting v2

Let me start off by saying that the work done by Himadri here is a great example at the flexibility of SPE. Not long ago Adam posted about Remoting in SPE, it became clear that we needed to have a Windows PowerShell module that users can setup outside of Sitecore that would come with all the necessary commands to interact with SPE. In our 3.1 release we included the module, so feel free to grab that now.

In this post I would like to show some recent enhancements made in 3.2 that will make interacting with SPE even better!

The packaged Windows PowerShell module can be found on the marketplace listed as SPE Remoting. That is the preferred method for interacting with SPE outside of the Sitecore environment. If you wish to use the same code from within the browser, such as to interact with another instance of SPE, you'll find the commands under here:
master:/system/Modules/PowerShell/Script Library/Platform/Functions/Remoting2

We've included all of the documentation below in our book.
When you execute the script or import the module you'll get the following commands:
  • New-ScriptSession - This can be reused between calls to all the other commands.
  • Invoke-RemoteScript - Best option for performing any remote script execution.
  • Send-MediaItem - Remotely upload.
  • Receive-MediaItem - Remotely download.
Let's walk through a few examples at using the commands.

Create a new session object that will contain a reference to the SPE session id and the web service proxy. Next we invoke a scriptblock on the server within the session.

If you would like to download images from the media library you can do something as simple as the following:

If you would like to upload images from the filesystem to the media library you can do something like this: