Tim

Footprints in the snow of a warped mind

Thursday, October 18, 2012

Where to find me

Flickr Icon  Twitter Icon  Linked In Icon  FaceBook Icon  Windows Live Alerts Butterfly  RSS 2.0 

FreeAgent Small Business Online Accounting
Business Protection by Crisis Cover

Tag Cloud

AJAX (4) Analysis (3) ASP (6) ASP.Net (59) Error Reporting (4) Web Service (2) WSDL (1) Atlas (2) Azure (1) Born In The Barn (1) Business (89) Business Start-up Advice (32) Client (17) Expanding Your Business (23) Recruitment (1) C# (22) Canoeing (4) Canoe Racing (5) Cheshire Ring Race (5) Racing (2) Training (4) CIMA (1) Cisco (1) 7970G (1) CMS (1) Code Management (1) Cohorts (4) Commerce4Umbraco (1) Content (1) Content Management (1) Content Management System (1) CSS (4) dasBlog (5) DDD (2) DDDSW (1) Design (11) Icons (1) Development (26) Domain Names (1) eCommerce (12) Employment (2) General (39) Christmas (6) Fun and Games (11) Internet (22) Random (46) RX-8 (8) Git (1) Google (1) Google AdWords (1) Google Analytics (1) Hacking (1) Helpful Script (3) Home Cinema (2) Hosting (2) HTML (3) IIS (11) iPhone (1) JavaScript (5) jQuery (2) Marketing (6) Email (1) Multipack (1) MVC (1) Networking (3) Nintendo (1) Nuget (1) OS Commerce (1) Payment (1) Photography (1) PHP (1) Plugin (1) PowerShell (3) Presentation (1) Press Release (1) Productivity (3) Random Thought (1) Script (2) Security (2) SEO (6) Server Maintenance (7) Server Management (12) Social Media (2) Social Networking (3) Experiment (1) Software (11) Office (5) Visual Studio (14) Windows (5) Vista (1) Source Control (1) SQL (9) SQL Server (19) Statistics (2) Stored Procedure (1) Sublime Text 2 (1) SVN (1) TeaCommerce (1) Testing (2) The Cloud (1) The Site Doctor (136) Turnover Challenge (1) Twitter (3) uCommerce (13) Umbraco (31) 2009 (1) 2011 (1) Useful Script (2) Virtual Machine (1) Web Development (71) WebDD (33) Wii (1) Windows Azure (1) XSLT (1)

Blog Archive

Search

<October 2012>
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

Recent Comments

Blog Archive

Various Links

Google+

Blogs I Read

[Feed] Google Blog
Official Google Webmaster Central Blog
[Feed] Matt Cutts
Gadgets, Google, and SEO
[Feed] Ol' Deano's Blog
My mate Dean's blog on my space, equally as random as mine but not off on as much of a tangent!
[Feed] Sam's Blog
Sam is one of my younger brothers studying Product Design and Manufacture at Loughborough, this is his blog :) Enjoy!

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

newtelligence dasBlog 2.2.8279.16125

Send mail to the author(s) Email Me (Tim Gaunt)

© 2013 Tim Gaunt.

Sign In

# Thursday, October 18, 2012

CSS frameworks and column class names €“-why I think they are wrong

Thursday, October 18, 2012 1:47:57 PM (GMT Daylight Time, UTC+01:00)

Before starting the new uCommerce demo razor store, we had a chat through the options as far as CSS frameworks were concerned. The main consideration we had was that it had to be a framework that the community was familiar with as we weren't looking to explain the framework but rather demo the uCommerce functionality.

The frameworks we considered using were:

One thing that has been bothering me for some time with all these various frameworks is the class naming convention they use for the columns.

The issue I have is that I still don't think it's clear and leaves me having to think -especially when you start moving over to a responsive design.

An Alternative Solution

For quite some time now we've been using an alternative class naming convention which I personally find far more descriptive and doesn't care about how many columns you're using.

It's simple, name the column classes as though they're "upside down fractions" e.g.: a column that spans 1 of two 2 columns on the page would be: .col-2-1 (there are two columns per row and you want this one to span 1 of those two).

Why's it better? Mainly because it's descriptive -so you know how may columns will be in the row and how many this column spans. You can easily spot areas to group columns together e.g. .col-4-2 should be .col-2-1. Want a 3 column layout with the centre column being 50% of the page? No problem:

<div class="col-4-1">
	<p>Column 1</p>
</div>
<div class="col-2-1">
	<p>Column 2</p>
</div>
<div class="col-4-1">
	<p>Column 3</p>
</div>

So how does it compare?

Assuming we're working on a 12 column grid:

Framework Full Width Half Width Third Width Grid View
960 Grid System .grid_4 .grid_4 .grid_4 2012-10-18 CSS Grid - 960
Twitter Bootstrap .span12 .span6 .span4 2012-10-18 CSS Grid - Bootstrap
Kube N/A .Half .Third 2012-10-18 CSS Grid - Kube
blueprint .span-12 .span-6 .span-4  
Ours .col-1-1 .col-2-1 .col-3-1 2012-10-18 CSS Grid - Ours

 

I realise that some people don't like fractions but I find that this naming convention a little easier to work with when mixing and matching column layouts. What do you think? How do you name your column classes?

 

Don't forget to follow me on Twitter.

# Wednesday, June 06, 2012

New domain name scam

Wednesday, June 06, 2012 11:27:48 AM (GMT Daylight Time, UTC+01:00)

This email almost caught me out the other day:

29-05-2012 16-00-13 Domain Scam

The client has been interested in the .com before but I couldn't recall whether it was something we had bought for them or not so I checked it out and it was actually free -so it's basically a $250 domain registration!

Don't be caught out, make sure you check the domain names yourself first.

 

Don't forget to follow me on Twitter.

# Sunday, May 27, 2012

From Side Line to Full Time - my DDD South West presentation

Sunday, May 27, 2012 7:42:37 PM (GMT Daylight Time, UTC+01:00)

imageThanks to all of you who came to my DDD South West talk, I really enjoyed and I hope you did too (and found it useful).

For the benefit of you who came -and those who couldn't make it, here's the slide deck from my DDD South West talk on getting started in business.

 

 

Note: Apparently you need to view the slide deck in full screen to view the notes (you'll need them).

If you have any questions/feedback etc please get in touch via email or twitter, I'd love to hear from you.

Finally, please do let me know how you get on, I'd love to hear what you get up to!

 

Don't forget to follow me on Twitter.

# Friday, May 18, 2012

Quick Pro Tip: Running low on disk space? Delete your hiberfil.sys

Friday, May 18, 2012 3:03:48 PM (GMT Daylight Time, UTC+01:00)

I freed up about 10GB of space on my C drive this afternoon by simply disabling Hibernation:

Before

QuickFreeUpSpaceTip-Before

After

QuickFreeUpSpaceTip-After

Step 1: Open Command Prompt as an Administrator

Step 2: Type powercfg -h off and hit enter -if nothing else is output then you've done it right:

QuickFreeUpSpaceTip-CMD

Step 3: Marvel at your additional disk space

That's it.

The hiberfil.sys file is a (large) file which stores the the current state (memory) of your computer. You can't just hit delete on it as it's always in use but you can free up a lot of space quickly by disabling Hibernate (you might as well if you never use it):

 

Don't forget to follow me on Twitter.

# Saturday, May 12, 2012

Umbraco powered CheckBoxList or DropdownList nodes in uCommerce admin area

Saturday, May 12, 2012 2:53:24 PM (GMT Daylight Time, UTC+01:00)

CustomControlInUCommerce2uCommerce is a great e-commerce engine for Umbraco and high on our list of options when evaluating new e-commerce projects at The Site Doctor.

One thing that has always bugged me however is the lack of extensibility on the admin backend. This is something I've discussed with Søren in the past and I believe is on the cards to be resolved in the upcoming v3 release but we wanted to see if there was a way we could get it working in the current release. Thanks to Dan's digging we've found it is (ish).

Skip to the downloads.

A Little Background

Before I dive into the code and overview how you should get it all wired up, I think it's worth understanding how uCommerce is structured out of the box:

  • Each uCommerce section has it's own folder under the "umbraco/uCommerce" folder so if you want to extend the functionality for the "Product Catalog" area then you will need to look in the "Catalog" folder.
  • The ASPX files are the main containers (e.g. EditProduct.aspx) and don't generally include any logic as they load up the various UserControls (the ASCX files) as tabs.
  • Adding custom tabs can be done through the uCommerce_AdminTab table but that's outside the scope of this post but Lasse has a good introduction on his blog.

As we plan to alter the product details edit functionality, we'll need to make a few changes to EditProductBaseProperties.ascx. It's worth taking a quick look around the file if you've not before as we've re-ordered the boxes, added classes and hidden the SKU field before, all of which is often useful. You'll notice at the end of the file there's  a repeater "ProductPropertyRepeater" -this is where uCommerce outputs the various custom properties you've setup.

Why's it useful?

Have you ever felt limited by the options of Text/Boolean/Enum/Image/Number and RichText and wished you could implement your own cool control like an image cropper or checkbox list? What about driving that control with data from Umbraco or another data source? If you have, this is the blog post for you as it handles all those scenarios.

Getting Started

If you don't want to know how to do this yourself you can click here to skip to the downloads and get started straight away.

Caution: If you want a CheckBoxList or your own custom control, you need to be running v2.6 as it adds IWebControlAdapter. As of v2.6 I'm not convinced IWebControlAdapter is fully implemented as it allows you to retrieve the value from the control but we will need to override the UserControl which outputs the control which feels hacky.

Create a custom control

Unless you want a fairly standard control (TextBox, CheckBox, DropDownList or ContentPickerUCommerce) you'll need to create a control which uses the IWebControlAdapter interface. This will mean uCommerce is able to get the value from it. You will need to implement two methods:

  • Adapts(Control) - allows you to specify whether it is a control you will be managing.
  • GetValue(Object) - allows you to specify what value the control contains In it's entirety it could be pretty simple:
namespace TheSiteDoctor.Web.uCommerce.Admin.UI
{
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Linq;

    using UCommerce.Presentation.Web.Controls;

    public class UCommerceUmbracoDrivenCheckboxList : CheckBoxList, IWebControlAdapter
    {
        public bool Adapts(Control control)
        {
            return control is UCommerceUmbracoDrivenCheckboxList;
        }

        public object GetValue(object control)
        {
            var li = (UCommerceUmbracoDrivenCheckboxList)control;
            var values = (from ListItem listitem in li.Items where listitem.Selected select listitem.Value).ToList();
            return string.Join(",", values);
        }
    }
}

Create your own DataTypeControlFactory

uCommerce uses DataTypeControlFactory to determine what control to render in the editor so you'll need to override the default implementation because it doesn't look for IWebControlAdapters at the moment.

This is simple enough, it needs to accept a Page (the page you'll be adding the control to) and the work out what control it should output e.g.:

public class CustomDataTypeControlFactory : DataTypeControlFactory
{
    Page _page;

    public CustomDataTypeControlFactory(Page page)
        : base(page)
    {
        _page = page;
    }

    public Control CreateCustomControl(IProductProperty productProperty)
    {
        if (productProperty == null)
            throw new ArgumentNullException("productProperty");

        return CreateCustomControl(productProperty.ProductDefinitionField, productProperty.Value);
    }

    private Control CreateCustomControl(ProductDefinitionField productDefinitionField, string value)
    {
        var fieldType = productDefinitionField.DataType.TypeName;

        if (fieldType.StartsWith("Something"))
            return base.CreateControl(productDefinitionField, value);

        // Some logic to work out whether you should be creating the control
        return customControl;
    }
}

Add a custom ProductPropertyEditor.ascx

Now you'll need to create your own ProductPropertyEditor.ascx which calls your new DataTypeControlFactory:

public partial class CustomUcommerceProductPropertyEditor : ProductPropertyEditor
{
    protected new void Page_Load(object sender, EventArgs e)
    {
        InitializeControl();
    }

    public override void DataBind()
    {
        base.DataBind();
    }

    private void InitializeControl()
    {
        Controls.Clear();
        Control child = CreateControlToRender();
        Controls.Add(child);
    }

    private Control CreateControlToRender()
    {
        if (ProductProperty == null)
        {
            throw new InvalidOperationException("Cannot create control, ProductProperty not set.");
        }

        var factory = new CustomDataTypeControlFactory(Page);
        return factory.CreateCustomControl(ProductProperty);
    }
}

You may notice that we're clearing the controls in the InitializeControl which is called from Page_Load whereas uCommerce makes the same call from DataBind(); this is intentional. I've not yet figured out why but if you don't do it from Page_Load, uCommerce still outputs a TextBox.

Wire it all up

To get this all outputting, you now need to replace the call to ProductPropertyEditor in EditProductBaseProperties.ascx with a reference to your own ASCX file, you can do this by updating this line:

<%@ Register Src="~/Umbraco/UCommerce/Controls/ProductPropertyEditor.ascx" TagPrefix="commerce" TagName="ProductPropertyEditor" %>

To:

<%@ Register Src="~/Umbraco/UCommerce/Controls/[YourFileNameHere].ascx" TagPrefix="commerce" TagName="ProductPropertyEditor" %>

Edit your Presenters.config

At this point if you were to load up your uCommerce backend you'd find that it outputs as intended but when you saved the file you'd either get an error or the value doesn't save. The reason for this is although you've replaced the display aspect of the editor, uCommerce is still looking at it's old "GetValue" implementation instead of your new control.

Open /umbraco/ucommerce/configuration/presenters.config and add a reference to your control which implements the IWebControlAdapters interface:

<component id="UCommerceUmbracoDrivenCheckboxList"
			service="UCommerce.Presentation.Web.Controls.IWebControlAdapter, UCommerce.Presentation"
			type="Your.Custom.uCommerce.Namespace.ControlName, Your.Custom.uCommerce.AssemblyName" 
			lifestyle="PerWebRequest"/>

That's it, you're done, you can now add your own controls to the backend of uCommerce.

CustomControlInUCommerce

Download

To make life easier I've packaged the files up into an Umbraco package and have also added the source:

Download the source code with references (C#) - 800KB

Download the Umbraco Package - 12KB

Instructions on using the package

If you download the source code you may have noticed we're doing some funky things with the DataTypeName. The idea behind the control is that it allows us to output a DropDownList or CheckBoxList containing values based on a Document Type and start node purely from the name of the DataType.

I can go into more detail about how we're doing this if it's of interest, just leave me a comment below but to start using it straight away you will need to use the following naming convention for your DataType's name:

  1. TSD_: This is the prefix we use to identify whether it's a control we should be handling
  2. Control Type: Currently this can either be "ddl" for a DropDownList or "chkl" for a CheckBoxList
  3. Start Node Id: This should be the id of the Umbraco parent node. You can cheat and use the root node but it's best to use the parent
  4. Document Type: This is the Document Type's alias to use

Example: if you wanted a list of checkboxes for ShapeType (as above) then your name would be: TSD_chkl_1234_ShapeType and a DropDownList would be: TSD_ddl_1234_ShapeType

What next?

This is something we're using more and more in uCommerce these days as it allows us to use the power of Umbraco to power uCommerce which is allowing us to do some really interesting things. Although we'll only be developing it as we need it at the moment we do have plans to add support for:

  • Radio Button Lists
  • Image Cropper
  • Adding nesting to the list of items (to offer better support for hierarchical data)
  • Powering it by the members and media sections
 

Don't forget to follow me on Twitter.

# Tuesday, April 17, 2012

Quick pro tip - Open File in Sublime from Visual Studio

Tuesday, April 17, 2012 4:58:45 PM (GMT Daylight Time, UTC+01:00)

sublime-text-2This is one of those really simple little gems that helps productivity ten-fold. Firstly, regardless of whether you're running a PC, Mac or Linux, if you've not already come across Sublime Text 2 you should go download it right now.

There are a ton of amazing features in Sublime (enough to warrant an talk by Dan Kendall no less), some of them are available in Visual Studio but none are quite as rich. Things like the multi-selection/multi-cursor feature are just awesome for quickly making the same changes in multiple places, not to mention the "select this word throughout the document" shortcut which has saved me hours already.

So what's my quick tip?

Rather than copying/pasting the path in the open dialog each time you want to edit the file, Dan pointed out to me the other day that you can easily wire it up as an external tool and then add a shortcut so you can open the current file in a flash.

Here's a step-by-step guide:

7B3A4FE1-C8AB-43AC-96D3-353B3A6753AE

DCE35C2C-D18D-4498-BA4A-B76B1F8299E9

Optional Additional Enhancement

You can wire up a keyboard shortcut for extra speed, again under the "Tools" menu, go to "Options" and then "Keyboard" (under "Environment"):

ED2789BC-6B50-4AFA-A477-3C27AEDD576D

ED2789BC-6B50-4AFA-A477-3C27AEDD576D-sm

2DEAB140-EA74-4FA9-BD80-21970F22CAF5

Thanks Dan for the heads up on this one.

 

Don't forget to follow me on Twitter.

# Friday, April 06, 2012

How to generate customer purchase cohorts from uCommerce data

Friday, April 06, 2012 10:02:29 AM (GMT Daylight Time, UTC+01:00)

I've had a couple of people ask how they can create customer purchase cohorts from their uCommerce data since my last post so here's a quick script.

Depending on how you've setup your uCommerce store, the customer ids might be different so instead of using customer id. I would use the email address of the customer personally as the identifier as this means you'll be able to analyse those customers who have chosen to check out anonymously Smile

Here's the SQL to output the data in a format suitable for www.quickcohort.com.

WITH Actions (FirstAction, LastAction, UniqueId)
AS (
	SELECT min(dateadd(dd, datediff(dd, 0, o.CompletedDate), 0))
		 , max(dateadd(dd, datediff(dd, 0, o.CompletedDate), 0))
		 , ltrim(rtrim(LOWER(cc.EmailAddress)))
	FROM [uCommerce_PurchaseOrder] o LEFT JOIN uCommerce_Customer cc ON cc.CustomerId = o.CustomerId
	GROUP BY ltrim(rtrim(LOWER(cc.EmailAddress)))
)
SELECT a.[FirstAction]
	 , a.[LastAction]
	 , count(a.[UniqueId]) AS [CountOfCustomers]
FROM
	Actions a
GROUP BY a.[FirstAction]
	   , a.[LastAction]
HAVING 
	min(dateadd(dd, datediff(dd, 0, a.[FirstAction]), 0)) IS NOT NULL
ORDER BY a.[FirstAction]
	   , a.[LastAction]

GO

 

Not using uCommerce as your e-commerce provider? Let me know and I'll knock up a script for you.

 

Don't forget to follow me on Twitter.

# Wednesday, February 22, 2012

How to generate the data needed for a cohort chart- cohort analysis Part 3

Wednesday, February 22, 2012 1:15:53 PM (GMT Standard Time, UTC+00:00)

Sean Ronan pointed out on twitter that "what" the columns on www.quickcohort.com are which is a good point so I thought I would fill in the gaps a little. The data for a cohort is fairly simple and can be as granular as you decide but the columns needed are:

  1. First Action Date/Time
  2. Most Recent Action Date/Time
  3. Count of customers which have this First/Most Recent Action Date/Times

Most of the time you can strip the time part from the date/time (especially if you're looking at the data on a month basis) but the tricky part is getting the count of users within each date grouping. You can't just select min/max dates as you need the data grouped by your unique customer identifier. If you're running SQL Server 2005+ then you've got the benefit of Common Table Expressions.

For this example, I've assumed a simple order table structure which contains a Customer Reference (CustomerId) and an Order Date (OrderDate). You could however use any date and identifier which groups actions together e.g. ProfileId and LastLoginDate.

SQL 2005 or later

WITH Actions (FirstAction, LastAction, UniqueId)
AS (
	SELECT min(dateadd(dd, datediff(dd, 0, o.[OrderDate]), 0))
		 , max(dateadd(dd, datediff(dd, 0, o.[OrderDate]), 0))
		 , o.[CustomerId]
	FROM Orders o
	GROUP BY CustomerId
)
SELECT a.[FirstAction]
	 , a.[LastAction]
	 , count(a.[UniqueId]) AS [CountOfCustomers]
FROM
	Actions a
GROUP BY a.[FirstAction]
	   , a.[LastAction]
ORDER BY a.[FirstAction]
	   , a.[LastAction]

Otherwise, I think you'll need to write something using temporary tables e.g.:

Pre SQL 2005

CREATE TABLE #Actions(
	FirstAction SMALLDATETIME, 
	LastAction SMALLDATETIME, 
	UniqueId INT
)
INSERT INTO #Actions
(
  FirstAction
 ,LastAction
 ,UniqueId
)
SELECT min(dateadd(dd, datediff(dd, 0, o.[OrderDate]), 0))
	 , max(dateadd(dd, datediff(dd, 0, o.[OrderDate]), 0))
	 , o.[CustomerId]
FROM #Orders o
GROUP BY CustomerId

SELECT a.[FirstAction]
	 , a.[LastAction]
	 , count(a.[UniqueId]) AS [CountOfCustomers]
FROM
	#Actions a
GROUP BY a.[FirstAction]
	   , a.[LastAction]
ORDER BY a.[FirstAction]
	   , a.[LastAction]

DROP TABLE #Actions

This should then generate some data that looks like this:

FirstAction LastAction CountOfCustomers
2011-03-01 2011-03-01 1
2011-03-01 2011-04-01 1
2011-04-01 2011-06-01 1
2011-05-01 2011-10-01 1
2011-06-01 2011-11-01 1
2011-07-01 2011-08-01 1
2011-08-01 2011-08-01 1
2011-09-01 2011-12-01 1
2011-10-01 2012-02-01 1
2011-11-01 2012-02-01 1
2011-12-01 2012-02-01 1
2012-01-01 2012-01-01 1
2012-02-01 2012-02-01 2

Which you should just be able to drop into www.quickcohort.com. I've not written a version for MySQL as I suspect someone far better at MySQL will be able to pop something together but the pre SQL 2005 script should work.

 

Don't forget to follow me on Twitter.