Theming websites in Umbraco using SASS and HTML5 color picker

Sass is used as the stylesheet language for an Umbraco website that I’ve been building recently and one of the requirements of the project is for the content editors to be able to change the colours of the website depending on the brand colours.

Sass variable defaults work really well for this. It meant that I could create a default variable for a colour e.g.

$brand-color: #0074BE !default;

Then for each website in Umbraco I could essentially override that variable and when compiled, this value will be used instead:

$brand-color: #FFFFFF;

On a static website, this all worked great but I had to figure out a way to get this to work in Umbraco.

The first step was to allow the Content Editors to change the theme colours. I did this using the lightweight HTML5 Color Picker :

umbraco theming html color picker

These fields are stored as HEX which is perfect.

The next step was to get these HEX values into the Sass and to compile it. This was achieved by using LibSass Host for .NET .

What I ended up doing is creating an UmbracoApiController that was called from the Master view that then returns the CSS for that website:

@{ 
var siteId = UmbracoContext.Current.PublishedContentRequest.PublishedContent.Site().Id;
}

<link rel="stylesheet" href="/umbraco/api/css/get?id=@siteId">

As this is a Web Api controller, I had to pass the website id into it, in order to use it.

Now I needed to read in all the Sass files from the file system:

var sassFolderPath = HttpContext.Current.Server.MapPath("~/styles/sass/");
var sass = "";

foreach (var filePath in Directory.GetFiles(sassFolderPath, "*.scss", SearchOption.AllDirectories))
{
    sass += File.ReadAllText(filePath, Encoding.UTF8);
}

Once I had all that, I could then insert the HEX values from Umbraco into theme variables:

var homePage = UmbracoContext.Current.ContentCache.GetById(websiteId);
sass += ProcessColour("themeMainColour", "color-brand--main", homePage);
sass += ProcessColour("themeMainContrastColour", "color-brand--main-contrast", homePage);

private static string ProcessColour(string umbracoFieldName, string sassVariableName, IPublishedContent homePage)
{
    if (!homePage.HasValue(umbracoFieldName)) return "";

    var hex = homePage.GetPropertyValue(umbracoFieldName).ToString();
    return $"${sassVariableName}: {hex};\r\n";
}

The sass string variable can now be passed into LibSass to compile it and I get some lovely CSS back!

 var css = SassCompiler.Compile(sass, "input.scss").CompiledContent;

This CSS can then be returned in the HttpResponseMessage of the Api method.

I’ve added a whole lot of caching around this as well so one extra thing I had to do in order to expire the cache was to implement a ApplicationEventHandler so whenever the Homepage of a website is published, it expires the CSS cache for that website.

 

Theming websites in Umbraco using SASS and HTML5 color picker

AngularJS ui-sortable on a table in Umbraco

I was building a custom dashboard recently and needed to give the client the ability to change the sort order of how attributes were displayed on the website and it turned out to be a lot easier than I was expecting.

From the start I wanted it to work just like the reorder functionality on Document Types:

Umbraco Reorder

After a bit of digging, it seemed that this was using ui-sortable and is automatically included in Umbraco. You can find it in the folder \Umbraco\lib\angular\

This meant that I could attach ui-sortable to the <tbody> element of my table and assign the attributes data to the ng-model:

<table class="table">
    <thead>
        <tr>
            <th scope="col">Sort Order</th>
            <th scope="col">Attribute Name</th>
        </tr>
    </thead>
    <tbody ui-sortable ng-model="attributes">
        <tr ng-repeat="row in attributes" id="{{row.id}}">
            <td>{{row.sortOrder}}</td>
            <td>{{row.attributeName}}</td>
        </tr>
    </tbody>
</table>

Then, just like magic, you can drag and drop the rows in the table!

As the attributes are allocated to the ng-model of the table body, angular keeps the object in sync with the order displayed and then I could save that new order back to the database with ease.

AngularJS ui-sortable on a table in Umbraco

Creating Hard Bounces for Sitecore Email Experience Manager in code

This week I’ve been working on integrating with a 3rd party API for when Sitecore Email Experience Manager receives a hard bounce from a contact’s email account.

Creating the processor for the <exm.recipientListManagement.add> pipeline is quite easy as per usual but mimicking a hard bounce isn’t as easy as I thought.

Over on Sitecore Slack, Pete Navarra had a good idea of sending an email to a hard bounced account like this stack overflow answer but that wasn’t an option for me as on my dev machine all the EXM emails are getting caught by my local Papercut SMTP server.

Luckily with a few messages to the rest of the team I’m working with, someone had already done this by building up a bounce message, encrypting the details and then passing it into a BouncedMessageHandler.

Here’s a snippet of code to do it:

IStringCipher stringCipher = 
  Factory.CreateObject("exmAuthenticatedCipher", true) as IStringCipher;

if (stringCipher != null)
{
    BouncedMessageHandler bouncedMessageHandler = 
      new BouncedMessageHandler(
    Factory.CreateObject("exm/bouncedMessagesTaskPool", true) 
       as ShortRunningTaskPool,
    Factory.CreateObject("exm/recipientListManagementTaskPool", true) 
       as ShortRunningTaskPool);

    Random random = new Random();
    string messageId = "5beff565-cccb-4a36-83ba-17f66872d770";
    string contactId = "0a53d8ce-77e1-4c30-a903-9f128535fa99";
    string emailAddress = "test@test.com";

    List<Bounce> bouncedMessages = new List<Bounce>
    {
        new Bounce
        {
            Id = random.Next().ToString(),
            BounceReason = "reason",
            BounceType = BounceStatus.HardBounce,
            CampaignId = "",
            ContactId = stringCipher.Encrypt(contactId),
            EmailAddress = emailAddress,
            MessageId = stringCipher.Encrypt(messageId)
        }
    };

    bouncedMessageHandler.HandleReportedMessages(bouncedMessages);
}

 

Creating Hard Bounces for Sitecore Email Experience Manager in code

Moving email campaigns between environments in Sitecore

I’ve been doing a lot of work with Email Experience Manager recently and when I’ve installed a package on the target environment containing the items for the campaign they don’t appear in the EXM interface even though they appear in the Sitecore tree.

One simple question over on the Sitecore Slack Channel and Steve McGill pointed me in the direction to get it fixed.

Once your items have been imported into your target environment you can go to the EXM admin page at {CMURL}/sitecore/admin/messagestatistics.aspx

exm-admin-page-sitecore

You then click on the Upgrade button it will find the newly imported emails and create a Sitecore SQL campaign record if it doesn’t exist already.

You will now see your imported campaigns in Email Experience Manager.

For automated messages that I am using, there also seems to be one final link between the Campaign Item and the Email Message Item that also needs to be connected in order for tracking to work. The one way to kick this in to gear is to open the message in EXM, click on the “Full email campaign” link, click on the “Delivery” tab and then click the “Deactivate” button and then once that completes, click on the “Activate Message” button and the link between the two items will be created.

 

Moving email campaigns between environments in Sitecore

Sitecore Data Provider Resources

I was recently given some work to improve a Sitecore Data Provider that connects into a 3rd party DAM system called WebDAM. My first port of call was the Sitecore documentation which was only slightly helpful in explaining the theory but not really any real world examples to help me. My issue was also being unable to start from scratch as there wasn’t time for that so I headed over to Google. I pretty much spent days trawling the results for help and thought I would post the most useful links that I found as I finished my work by combining code from all of these:

The one project I struggled to get a hold of was BitsOnTheRun by Nick Wesselman. I eventually found it on the old marketplace but thought I would upload it to my Github just in case somebody else was looking for it: https://github.com/RyanDurkin/sitecore-bits-on-the-run

Without the awesome Sitecore community I probably would have never completed the work so thanks to everyone in the links above and hopefully this post will help someone else in the community also.

Sitecore Data Provider Resources

Sitecore PowerShell script to list unused media items with a prompt for folder location

I was recently asked to produce a report of all the unused media items in Sitecore for a specific Region folder and if you have the PowerShell extensions installed then there is a great one in there called “Media items not used by content items”.

Unfortunately this takes a very long time to run if you have a huge amount of media items in your library and didn’t allow the end user to specify a folder which lead me to extend it a little bit.

By extending the original script by Michael West and adding a Read-Variable prompt it gives the end user more flexibility:

$result = Read-Variable -Parameters `
 @{ Name = "item"; Title="Analyse subitems of"; Tooltip="Folder you want to analyse."; Root="/sitecore/media library/"} `
 -Title "Find all media items that are not in use" -Width 600 -Height 200 `
 -OkButtonName "Proceed" -CancelButtonName "Abort"

Which displays like so:

sitecore powershell read item prompt

You then get a brilliant list view of the results once the script has finished which allows the end user to export as CSV, Excel etc

sitecore powershell script dialog report list

The full script can be found here: https://gist.github.com/RyanDurkin/992aaff199b706a3a7920d956055f529

Sitecore PowerShell script to list unused media items with a prompt for folder location

Eating Healthy Whilst Working From Home

It’s a proven fact that working from home is bad for your health. OK, that’s a lie but since going freelance I’ve completed a number of remote contracts which means I spend my brew making time raiding the cupboards for biscuits and sweets which isn’t very healthy at all.

My fix for this was to spend a silly amount of money on Nakd Bars which are just raw fruit and nuts. This was a lot healthier but it wasn’t healthy for my wallet.

If you look on the back of the packet the ingredients couldn’t be any simpler. They’re all made from Dates, Cashews and Raisins.

Ingredients of a Nakd bar

As I’m a web developer my first thought was to Google “How to make your own Nakd bars” which turns out it’s really easy and this is how you do it:

Take one cup of cashew nuts:

Cup of cashew nuts

Put them in a food processor and blend until they turn into crumbs:

Cashew nuts in blender

Take one cup of any dried berries. This time I used cranberries:

Cup of cranberries

Place them in the food processor:

Cranberries in blender

Take one cup of dried dates without the stones aka pitted dates:

Cup of dates

Put them in the food processor with the cranberries:

Dates in blender

Blend them all together for a minute or two or until all the ingredients start to clump together:

Ingredients Combined

Line a small baking sheet with some cling film:

Baking sheet lined with cling film

Put all the ingredients on the sheet and compact it all together:

Ingredients pressed onto sheet

Place it in the fridge for 3-4 hours and then take it out and cut it up into whatever size you like:

Cut into pieces

I then put them in a plastic container to store in the fridge and snack on whenever I want:

Placed in container

I’ve tried all kinds of dried fruit and nut combinations but always keep the dates. You could also add protein powder, cacao powder and chia seeds if you like too.

Your food processor needs to be pretty robust to break down the nuts and then the dates so don’t try doing this in a Nutribullet. Also, even though your dates say they are pitted there could be a rogue stone in there which will get stuck on your blade so if things are going a bit crazy in your food processor it could be that.

To get these as cheap as possible I’ve found that Aldi do the cheapest nuts and dried berries and Asda do the cheapest dates. Aldi also do a great cheap range of Spirulina, Maca and Cacao Powder.

Eating Healthy Whilst Working From Home