so, I bastardized one of the pre-existing XML packages, and came up with this (I named the file recentmini.xml.config and saved it to Skins/Skin_1/XmlPackages):
Code:
<?xml version="1.0" standalone="yes" ?>
<package version="2.1" displayname="Recently Viewed Mini" debug="false" includeentityhelper="false">
<query name="RecentlyViewedProductsMini" rowElementName="Item">
<sql>
<![CDATA[
exec dbo.aspdnsf_GetRecentlyViewedProductsMini
@customerID,
@productID,
@invFilter,
@RecentlyViewedProductsNumToDisplay
]]>
</sql>
<queryparam paramname="@customerID" paramtype="system" requestparamname="CustomerID" sqlDataType="int" defvalue="0" validationpattern="" />
<queryparam paramname="@ProductID" paramtype="request" requestparamname="ProductID" sqlDataType="int" defvalue="0" validationpattern="^\d{1,10}$" />
<queryparam paramname="@invFilter" paramtype="appconfig" requestparamname="HideProductsWithLessThanThisInventoryLevel" sqlDataType="int" defvalue="1" validationpattern="" />
<queryparam paramname="@RecentlyViewedProductsNumToDisplay" paramtype="appconfig" requestparamname="RecentlyViewedProductsMini.NumberDisplayed" sqlDataType="int" defvalue="3" validationpattern="" />
</query>
<PackageTransform>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:aspdnsf="urn:aspdnsf" exclude-result-prefixes="aspdnsf">
<xsl:output method="html" omit-xml-declaration="yes" />
<xsl:param name="RecentlyViewedProducts.NumberDisplayed" select="aspdnsf:AppConfig('RecentlyViewedProducts.NumberDisplayed')"></xsl:param>
<xsl:param name="RecentlyViewedProductsGridColWidth" select="aspdnsf:AppConfig('RecentlyViewedProductsGridColWidth')"></xsl:param>
<xsl:template match="/">
<xsl:param name="encloseInTab" select="aspdnsf:EvalBool(/root/Runtime/EncloseInTab)" />
<xsl:param name="productID" select="/root/runtime/productid" />
<xsl:choose>
<xsl:when test="count(/root/RecentlyViewedProductsMini/Item) > 0">
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="border-style: solid; border-width: 0px; border-color: #{aspdnsf:AppConfig('HeaderBGColor')};" >
<tr>
<td align="left" valign="top">
<img src="{aspdnsf:LocateImageURL(concat('/skins/Skin_', /root/System/SkinID, '/images/site/recentlyViewed.gif'))}" border="0"/>
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<xsl:if test="$encloseInTab = true()">
<xsl:attribute name="style">
<xsl:value-of select="aspdnsf:AppConfig('BoxFrameStyle')"/>
</xsl:attribute>
</xsl:if>
<tr>
<td align="left" valign="top" class="RelatedProductsBoxStyle">
<p>
<b>
<xsl:value-of select="/root/Runtime/teaser" />
</b>
</p>
<xsl:choose>
<xsl:when test="aspdnsf:StrToLower(aspdnsf:AppConfig('RecentlyViewedProducts.ProductsFormat')) = 'grid'">
<xsl:apply-templates select="/root/RecentlyViewedProductsMini/Item" />
</xsl:when>
<xsl:otherwise>
<table width="100%" cellpadding="0" cellspacing="0">
<xsl:for-each select="/root/RecentlyViewedProductsMini/Item">
<xsl:variable name="pName" select="aspdnsf:GetMLValue(Name)"></xsl:variable>
<xsl:variable name="pSEAltText" select="aspdnsf:GetMLValue(SEAltText)"></xsl:variable>
<xsl:variable name="AltText">
<xsl:choose>
<xsl:when test="$pSEAltText=''">
<xsl:value-of select="$pName" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pSEAltText" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<tr>
<td width="100%">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td valign="center" style="padding-left:4px; text-align:center;">
<a href="/{aspdnsf:ProductLink(ProductID, SEName, 0, '')}">
<img src="/{aspdnsf:ProductImageUrl(ProductID, imageFilenameOverride, SKU, 'icon', 0)}" border="0" width="125"></img>
</a>*
</td>
</tr>
<tr>
<td width="100%" style="padding:4px;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="text-align:center;">
<a href="/{aspdnsf:ProductLink(ProductID, SEName, 0, '')}">
<xsl:value-of select="aspdnsf:GetMLValue(Name)" disable-output-escaping="yes" />
</a>
</td>
</tr>
<tr>
<td>
<span class="a2">
<xsl:value-of select="aspdnsf:GetMLValue(Description)" disable-output-escaping="yes" />
</span>
</td>
</tr>
<tr>
<td>
<xsl:if test="aspdnsf:AppConfigBool('DisplayOutOfStockProducts') = 'true'">
<xsl:value-of select="aspdnsf:DisplayProductStockHint(ProductID,'Product')" disable-output-escaping="yes" />
</xsl:if>
</td>
</tr>
</table>
</td>
</tr>
</table>
<xsl:if test="position() != last()">
<hr size="1" class="LightCellText"/>
</xsl:if>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
</table>
</td>
</tr>
</table>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$encloseInTab != true()">
<div style="height : 200px; padding-top: 20px; padding-left: 20px">
<xsl:value-of select="aspdnsf:StringResource('showproduct.aspx.42')" disable-output-escaping="yes" />
</div>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Item">
<xsl:variable name="delta">
<xsl:choose>
<xsl:when test="(count(/root/RecentlyViewedProductsMini/Item) mod number($RecentlyViewedProductsGridColWidth)) = 0">0</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($RecentlyViewedProductsGridColWidth)-(count(/root/RecentlyViewedProductsMini/Item) mod number($RecentlyViewedProductsGridColWidth))"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="rows" select="ceiling(count(/root/RecentlyViewedProductsMini/Item) div number($RecentlyViewedProductsGridColWidth))" />
<xsl:if test="$RecentlyViewedProductsGridColWidth = 1">
<tr>
<xsl:call-template name="ProductCell"></xsl:call-template>
<xsl:if test="ceiling(position() div number($RecentlyViewedProductsGridColWidth)) = $rows and $delta > 0">
<xsl:call-template name="FillerCells">
<xsl:with-param name="cellCount" select="$delta" />
</xsl:call-template>
</xsl:if>
</tr>
</xsl:if>
<xsl:if test="position() mod $RecentlyViewedProductsGridColWidth = 1 and $RecentlyViewedProductsGridColWidth > 1">
<tr>
<xsl:for-each select=". | following-sibling::*[position() < $RecentlyViewedProductsGridColWidth]">
<xsl:call-template name="ProductCell"></xsl:call-template>
</xsl:for-each>
<xsl:if test="ceiling(position() div number($RecentlyViewedProductsGridColWidth)) = $rows and $delta > 0">
<xsl:call-template name="FillerCells">
<xsl:with-param name="cellCount" select="$delta" />
</xsl:call-template>
</xsl:if>
</tr>
</xsl:if>
</xsl:template>
<xsl:template name="ProductCell">
<xsl:param name="pName" select="aspdnsf:GetMLValue(Name)"></xsl:param>
<xsl:param name="AltText">
<xsl:choose>
<xsl:when test="aspdnsf:GetMLValue(SEAltText)=''">
<xsl:value-of select="aspdnsf:GetMLValue(Name)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="aspdnsf:GetMLValue(SEAltText)" />
</xsl:otherwise>
</xsl:choose>
</xsl:param>
<td align="center" valign="top">
<a href="/{aspdnsf:ProductLink(ProductID, SEName, 0, '')}">
<xsl:value-of select="aspdnsf:LookupProductImage(ProductID, ImageFileNameOverride, SKU, 'icon', 0, $AltText)" disable-output-escaping="yes"/>
</a>
<br/>
<a href="/{aspdnsf:ProductLink(ProductID, SEName, 0, '')}">
<xsl:value-of select="$pName" disable-output-escaping="yes"/>
</a>
<xsl:if test="aspdnsf:AppConfigBool('DisplayOutOfStockProducts') = 'true'">
<xsl:value-of select="aspdnsf:DisplayProductStockHint(ProductID,'Product')" disable-output-escaping="yes" />
</xsl:if>
</td>
</xsl:template>
<xsl:template name="FillerCells">
<xsl:param name="cellCount"/>
<xsl:param name="CellWidth" select="100 div $RecentlyViewedProductsGridColWidth" />
<td width="{$CellWidth}%">*</td>
<xsl:if test="$cellCount > 1">
<xsl:call-template name="FillerCells">
<xsl:with-param name="cellCount" select="$cellCount - 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
</PackageTransform>
</package>
When combined with this Stored Procedure:
Code:
USE [AspDotNetStorefront]
GO
/****** Object: StoredProcedure [dbo].[aspdnsf_GetRecentlyViewedProductsMini] Script Date: 01/27/2009 19:05:32 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[aspdnsf_GetRecentlyViewedProductsMini]
@customerID int,
@productID int,
@invFilter int,
@recentlyViewedProductsNumToDisplay int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @HideProductsWithLessThanThisInventoryLevel int,
@RecentlyViewedProductsEnabled varchar(10),
@customerGUID uniqueidentifier
-- Insert statements for procedure here
-- Uncomment the following lines for testing purposes
-- select @customerID=58640
-- select @invFilter=1
-- select @recentlyViewedProductsNumToDisplay=3
SELECT @RecentlyViewedProductsEnabled = CASE ConfigValue WHEN 'true' THEN 1 ELSE 0 END FROM dbo.AppConfig WITH (NOLOCK) WHERE Name = 'RecentlyViewedProducts.Enabled'
SELECT @HideProductsWithLessThanThisInventoryLevel = CONVERT(int, ConfigValue) FROM dbo.AppConfig WITH (NOLOCK) WHERE [Name] = 'HideProductsWithLessThanThisInventoryLevel' AND ISNUMERIC(ConfigValue) = 1
IF (@HideProductsWithLessThanThisInventoryLevel > @invFilter or @HideProductsWithLessThanThisInventoryLevel = -1) and @invFilter <> -1
SET @invFilter = @HideProductsWithLessThanThisInventoryLevel
IF(@RecentlyViewedProductsEnabled = 1) BEGIN
SELECT @customerGUID = customerGUID FROM dbo.Customer WHERE CustomerID=@customerID
SELECT TOP (@recentlyViewedProductsNumToDisplay) p.ProductID, p.Name, p.SEName, p.SEAltText, p.imageFilenameOverride
FROM dbo.Product p
join (select ProductID, max(ViewDate) LastViewDate FROM dbo.Productview pv where pv.CustomerGUID = @customerGUID and pv.ProductID <> @productID GROUP BY ProductID) v on p.ProductID = v.ProductID
join dbo.productvariant pv WITH (NOLOCK) ON pv.ProductID = p.ProductID and pv.IsDefault = 1
left join (SELECT variantid, SUM(quan) inventory FROM dbo.inventory GROUP BY variantid) i ON pv.variantid = i.variantid
WHERE p.Deleted = 0 AND
pv.Deleted = 0 AND
p.published = 1 AND
pv.published = 1 AND
GETDATE() BETWEEN ISNULL(p.AvailableStartDate, '1/1/1900') AND ISNULL(p.AvailableStopDate, '1/1/2999')AND
(CASE p.TrackInventoryBySizeAndColor WHEN 1 THEN isnull(i.inventory, 0) ELSE pv.Inventory END >= @InvFilter OR @InvFilter = -1)
ORDER BY v.LastViewDate DESC
END
END
I can pull the recently viewed products into a compartmentalized feature that I can drop on any page, like so:
Code:
<div>(!XmlPackage Name="recentmini.xml.config"!)</div>
I have this in my home and sub templates, in a side bar area. This can be extended and improved by creating a new AppConfig record to store the number of MINI recently viewed items, then swapping the new AppConfig Key name in, in place of RecentlyViewedProductsMini.NumberDisplayed - I haven't had the need to do that, yet.
I hope this helps some of you!