Monday, November 9, 2009

An Example of using Edit Frames in Nicam

For those of you that work with, or used to work with, 5.3 Green Dots Web Edit functionality, you might really appreciate the ease with which you can create contextual editing menus.  The 6.0 Page Editor (with all its significant usability features and improvements) might have left you questioning your ability to implement the same contextual functionality.  Enter Edit Frames as of 6.1, a great new feature that should have you dreaming up some incredibly focused Page Editor-based contextual editing functionality.

John West, as always, has a great description of this functionality here.

For my discussion today, I wanted to show a couple of quick examples of where this could be used.  As you know, Sitecore Data Templates promote the encapsulation of complex content types.  Some fields in these Data Templates are presentation-driven (Short Description, Image), while others are meta-driven (Rating, Keywords, Category).  The Content Editor interface shows all fields on both sides of this fence in a comprehensive, section-organized form view.  In Page Editor, we get the very handy inline frame editing of all presented fields.  But what about those meta-fields behind the scenes?  Page Editor presents the “Blue Boxes” to split the screen and get to those fields behind the presented page.

image

Clicking on Edit the related item splits the screen and allows us to navigate the sections of fields that make up the News Article Data Template:

image

While this is intuitive and simple, we’re always striving to make this Page Editor experience as streamlined as possible.  Instead of splitting the screen and having to find a field (within what could be a very complex Data Template), it would certainly be nice to define the field(s) that the editor would be most interested in getting to, and to simplify and focus the editing interface even more.

Edit Frames allow for just that.  Let’s take this same example.  We’re editing a News Article (Nicam Camera K200D) that has fields for Title, Short Description, Image, etc.  Via the Online Marketing Suite, we article authors also want to tag this piece with the appropriate keywords that match up to our profile keys.  Let’s build an Edit Frame around the article’s title that allows us to see the checklist of Keywords with which to tag this article.

First, we need to define the Buttons that will be part of our Edit Frame contextual menu.  Sitecore provides a couple of handy default buttons (Insert and Edit).  For today, we’ll simply use the default behavior of Edit Field, but for you developers, you can already imagine that any command functionality can be invoked here.  The Buttons themselves are defined in the Core database (very much like the commands available to the Rich Text Editor).

image

Switching to the Core database and navigating to /sitecore/content/Applications/WebEdit/Edit Frame Buttons will show us all Edit Frame toolbars configured for the site.

image

The system is installed with the Default toolbar in place.  If an Edit Frame does not specifically call out a Buttons property, the Default is used.  Let’s copy the Default item, paste it under Edit Frame Buttons, and rename it Keywords.

image

If you select the newly renamed Keywords item, you’ll see that the Edit Frame toolbar has fields for a Title and Tooltip.  Expand the Keywords item to reveal the default Buttons available to it.  We’re using the Edit Button (you can delete this Insert button), and selecting it shows the fields available to the Field Editor Button template that it is based on.

image

The Fields field allows a pipe-separated list of fields that will become readily available to the Page Editor.  For our example, we’re using only one:

image

Now, with the toolbar in place and configured, we simply need to add the Edit Frame to a presentation control.  This Edit Frame can be added, of course, to a .NET or XSLT control.  Since the news article already has a NewsItem xslt to present its fields, let’s add the frame there:

<xsl:template match="*" mode="main">
<
sc:editFrame Buttons="/sitecore/content/Applications/WebEdit/Edit Frame Buttons/Keywords">
<
h1>
<
sc:text field="Title" select="." />
</
h1>
</
sc:editFrame>


Notice the Buttons property calls out the path in the Core database to the Keywords toolbar we set up.  The <sc:editFrame> itself will present hover-over region including any HTML we wrap it with:



image 



Clicking on the new Keywords (Default Title of the Keywords toolbar itself) drop-down shows us any buttons within the Toolbar.



image



And now we can easily edit the Keywords checklist field:



image



That’s all there is to it.  This article simply covered the mechanics…now we can think through the many creative places where this technique makes sense to make the Page Editor even more powerful.

Friday, September 4, 2009

Some simple API code to insert Sitecore content items

Derek Roberti, Sitecore Director of Technical Services, recently put together an excellent paper on a question we often discuss in various sales and technical services conversations:  how are we going to integrate our external data with Sitecore?  While Derek’s paper does a much better job at getting to the very important details around this subject, I’d like to create a snippet today that illustrates one simple and fundamental concept to matching up external data with Sitecore data templates.
I like to divide the discussion of integration of external data sources with the Sitecore content tree into the various "buckets" these integrations can fall into (there are more).
  • Presentation level integration, where standard controls coordinate fields from the CMS item with data from external sources (Web Service calls, db queries, enterprise system APIs, etc).  Often a key value (productID) allows the storage of descriptive, marketing-driven data in Sitecore, while allowing pricing and availability to remain the realm of the ERP system designed for its maintenance and accessibility.  This integration doesn’t require any API method in Sitecore, since no data is moved into the CMS—after presentation, the link is no longer necessary.
  • Content editor level integration, where lists and other data stored in external systems are referenced by content editors as they maintain Sitecore CMS items.  Custom editing interfaces, drop down and tree lists, etc. lookup values stored in external tables for the purposes of choosing values that will be stored in the CMS.
  • Data provider level integration, where permanent mappings exist between Sitecore data template fields and fields of an external system.  Data continues to be maintained in its native system, while the Sitecore content tree exposes these data as native to Sitecore.  Items take advantage of externally manageable fields of data while also taking advantage of native Sitecore functionality, validation, workflow, security and more.
Somewhere in the middle bullet (or maybe prevalent enough to be its own) is the simple need to map existing data to Data Template fields in the effort to create new Sitecore content items.  This is certainly an important stage of many migration projects, where current enterprise content (whatever its current format or storage mechanism) needs to be mapped to the new and well-thought out Sitecore-enabled information architecture.
While this subject is an article in of itself, the effort can often be broken down to its main stages.  The purpose of this snippet is not to belittle the complexity and importance of any of these stages—deciding on an efficient mapping between current information and Sitecore Data Templates deserves the appropriate amount of time, skill and effort.  Instead, I wanted to end with a quick code sample that shows the stages quickly.  This example simply takes in an XML node as a parameter (representing an external RSS Feed), parses the feed and maps a couple of its fields to our newly created Sitecore Data Template, inserting new items under the “News” section of the content tree. 
The main stages:
  1. Analyze current content, information, organization of data.
  2. Create data template(s) in Sitecore to map current organization, taking advantage of Sitecore’s granular field types to encapsulate reusable components.
  3. Identify the area of the content tree where this content will be inserted.
  4. Map existing data to Data Template fields and create items under the appropriate parent.
  5. Rinse and repeat.
private void CreateRssItems(XmlNode rssItem)
{
// login in as an admin User
using (new Sitecore.SecurityModel.SecurityDisabler())
{
// The ContentDatabase points to the Master database.
// This assumes that this code runs in the Sitecore client.

Item News = Sitecore.Context.Database.GetItem("/sitecore/content/Home/News");
if (News != null)
{

// add a new Item based on  the Document Template
string title = rssItem.SelectSingleNode("title").InnerText;
title = Regex.Replace(title, @"[\[\]?:\/*""<>|]", "");
string description = rssItem.SelectSingleNode("description").InnerText;

// optionally, you can do this by referring to the content tree path
// of the data template you will use to map fields
Sitecore.Data.Items.Item NewRssItem = 
News.Add(title, Sitecore.Context.Database.GetTemplate("{A18D8CDE-AD94-4F84-BB74-648B20FE739A}"));
if (NewRssItem != null)
{

// optionally, impersonate a user with appropriate security priveleges
using (new Sitecore.SecurityModel.SecurityDisabler())
{
using (new EditContext(NewRssItem))
{
NewRssItem.Fields["Title"].Value = title;
NewRssItem.Fields["Description"].Value = description;
NewRssItem.Fields["__Display Name"].Value = title; 
}

}
}

}

}

}

One of those custom Web Forms for Marketers actions

I often have discussions with prospects and clients around the ease with which you can create custom submit actions for the Web Forms for Marketers module.  I finally had the opportunity to go through the mechanics and jot down the steps.
Because of the great, simple, consistent Item paradigm in Sitecore, each of the actions used by the Web Forms for Marketers module are themselves part of the content tree:
ActionsInContentTree
I copied the Save to Database action, pasted it and renamed it to “Save to CRM”.  We won’t implement anything like a CRM mapping today, but it sets up a good follow-up.  For today, just the mechanics….set up the item in the tree to call out to a class that follows the interface set up for an action, get access to the names and values of the submitted form.
As with this same capability to our code from workflow actions, validation actions, etc., the WFFM action provides the same ability to call out our class:
classSignature
Using .NET Reflector, I borrowed the implementation of the Send Mail action, stripped it down to just the code necessary to get access to the field names and values, and pasted it below:
using System;
using System.Web;
using Sitecore.Form.Core;
using Sitecore.Form.Submit;
using Sitecore.Form.Core.Client.Data.Submit;
using Sitecore.Data;

namespace NiCam.Classes.Mike
{
  public class SaveToCRM : ISubmit
  {

    public virtual void Submit(ID formid, AdaptedResultList fields)
    {
       foreach (Sitecore.Form.Core.Controls.Data.AdaptedControlResult formField in fields)
       {
          string fieldName = formField.FieldName;
          string fieldValue = formField.Value;
       }

     }

   }
}

This action will now be available to the Web Forms for Marketers UI drop down.

Monday, August 24, 2009

A simple XML Device Presentation Layer

At Sitecore we often talk about the many uses of the Device concept.  Sometimes this is obvious (a mobile device requesting content vs. a browser requesting content will expect some particulars around the HTML sent to it).  Sometimes it is a bit more subtle (Internet Explorer and Firefox continue to disagree about something, so I have a control that implements a method or CSS class a bit differently based on the detection of the browser).  One of the situations we often talk about is the ease of availability of an XML representation of each content item in the content tree.  This conversation often centers around integration points, where I can send an XSLT-translated XML document based on Sitecore content to an external application or Web service.
I wanted to prove in a quick concept--creating a Device presentation layer that shows an XML document based on the requested content item.  I took the easy way out in many areas of this, and I welcome real world "yeah, but this is actually how you should do it" wherever appropriate.

Basically, I started by creating the Device in Sitecore.  I called it XML and added it to the Devices in the content tree.

The new XML device is defined by any URL with xml=1 included in the query string.  To keep things simple, I created a new Layout (.aspx) file to handle requests from the XML device.  The Layout has a statically placed control (RenderXML.ascx) that does the work of:

  1. Creating an XML document out of the fields of the Sitecore context item (the currently requested item from the content tree)

  2. Transfer the request (Server.Transfer) to the newly created XML document (allowing the browser's CSS for XML files to format the display).
The code that does this, in the Page_Load event within RenderXML.ascs.cs, is shown below:
protected voidPage_Load(objectsender, EventArgs e)
        {
            Sitecore.Data.Items.ItemthisItem = Sitecore.Context.Item;
            XmlTextWriter writer = newXmlTextWriter(Server.MapPath("/layouts/dynamic/XmlDevice.xml"),System.Text.Encoding.UTF8);
            writer.WriteStartDocument();
            writer.WriteStartElement("item");
            writer.WriteAttributeString("name", thisItem.Name);

             foreach(Sitecore.Data.Fields.Fieldfld inthisItem.Fields)
            {
                    writer.WriteStartElement("field");
                    writer.WriteAttributeString("name", fld.Name);
                    writer.WriteAttributeString("value", fld.Value);
                    writer.WriteEndElement();
            }
               
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Close();
            Server.Transfer("/layouts/dynamic/XMLDevice.xml");        
        }

Height of Rich Text Fields in Content Editor

A short one for the Sitecore Admins out there. Question came up recently, "How do I make one of the Rich Text fields take up less screen real estate in Content Editor?"

Note the Long Description field below:











If you are choose to see Standard Fields (View-->Standard Fields), you'll be able to see the Appearance section of the template field. In this case, I expanded the node for my template and found the Long Description field. In the Long Description, I added the following to the Style field:


height: 20px;





Now the field in Content Editor takes up only the 20px height:









Friday, August 21, 2009

Starting Out

"It is content, or rather the consciousness of content, that fills the void. But the mere presence of content is not enough. It is style that gives content the capacity to absorb us, to move us; it is style that makes us care." --Tom Robbins, Another Roadside Attraction
A quick note about, well, what this is about. I want to capture (thoughts captured as blogs, blogs captured as more in-depth articles, more in-depth articles captured as--who knows?) an appreciation for the collaboration necessary in choosing and implementing a content management solution. This is of course true for all great software projects. This is of course true for all great projects. But with content management software projects, this collaboration seems to have a head start.

It seems like everyone is at the table early on--project managers, marketers, champions, network administrators, developers. The goal is (at least in comparison to many failed projects in the past) clear--let's create a Web presence that means something, that reacts to my visitor, that learns from that visitor to enable the system to grow on its own, guided in its growth by agreed upon business rules. Let everyone's voice be heard--quickly, efficiently, without departmental roadblocks shriveling ideas on the vine. At the same time, let me ensure our company voice is succinct and targeted, consistent and powerful. OK, clear goals...but aggressive too. This will require everyone's attention.

Developers will have to loosen the reins a bit, face the fears of a user community gone mad with the sweet taste of flexibility. Marketers will have to wield their new-found control with an architect's respect for foundations. Project managers will have to define communications workflows to keep the arrow pointing up and to the right. That's why you're all sitting at the table now....you're looking for the right tool to help you in this adventure.

Content Management is not new to you. You have lots of content--it's sprawling all over your site right now, failing to report back to you its conversations. Content Management isn't new to me either. Actually, technically it is. I've only recently starting working in this exciting and growing area of software. But I've understood the need for great conversations among great people seeking great goals for a while now. I've had well over a decade of managing software projects from all corners of the table. Now I've been given the privilege of working with what I consider to be the best tool for this job--Sitecore.

I will use this forum to relay the conversations I hear as groups like you make this very important decision to bring in an enterprise-level content management system. Depending on the day, I will dive into the technical and business considerations that are so important to this decision. I welcome your feedback and I appreciate your joining in this learning process.