Making Sense of the SharePoint World

Jan-212010

On Ends and Means

MCj04412850000[1]The Answer may be SharePoint, but Don't Forget the Questions!

One of the biggest reasons some SharePoint deployments fail is because they are "SharePoint Deployments".

People hear the buzz, and want to jump on the SharePoint bandwagon. They buy servers, attend training, install the software. Big bux are spent customizing and branding a SharePoint home page. Maybe there's a big roll-out promotion. Everybody says "Look! We've rolled out SharePoint!". And then...

Crickets.

All Dressed Up, and Nowhere to Go

But, you ask, what about all of those stories you hear about "uncontrolled growth"? People clamoring to get their own SharePoint sites? That's all true as well, but you need to consider why that is happening. In those cases, the people have a goal, and find that SharePoint is a great tool for making that goal a reality. The goal isn't to have a SharePoint site, per se. Rather the goal might be "easier document and calendar sharing", and SharePoint is used to attain it.

Simple Pleasures

Often those implementing SharePoint forget the KISS principle (Keep it Super Simple). SharePoint has a lot of great features and functions right out of the box. It is very tempting to try implementing all of them at once on the same site, sometimes even the same page. It is almost like when "desktop publishing" was made possible by Postscript laser printers. People discovered how easy it was to have a dozen fonts on a single page, and so that's what they did.

Similarly, in the early days of the web, as new features were added to web browsers, they started showing up everywhere on sites. (Does anyone remember the <Blink> tag?) And don't even get me stated on some of the early Flash-based sites. It got to the point where IBM was even poking fun at the designs in their commercials. "It's a Flaming Logo!" Why? Because we can!

The fact is, like the flaming logo, the fanciest features SharePoint has are worthless unless they are used in the service of some actual user need. For example: Assuming it is reasonably well implemented and up to date, the most used feature on any intranet is almost guaranteed to be the company phonebook or employee directory. Probably by an order of magnitude above any other function. It isn't fancy, but it is something people actually need on a regular basis.

As it turns out, SharePoint, with its personal profiles and My Sites, makes a great employee directory. :)

Form Follows Function

Of course, if all you needed was an employee directory, SharePoint would be overkill in the extreme. But put that directory in the context of a company intranet, with news and knowledge bases, collaboration and search. And here's a radical idea - Ask your users what they need first, and implement that! Maybe throw in a few things that are just for fun, like classified ads, or pictures from the company picnic. Suddenly you have a "destination" that will draw in your users and enhance the sense of community in your organization.

These are all things that could be (and often have been) done individually without SharePoint. But SharePoint gives you the tools you need to build and maintain these "applications" easily, quickly, and consistently - usually without custom code.

Now you can add your branding, and promote "Our-Net 2.0". Sure, it is a site based on SharePoint, but now you have put the horse before the cart, and given your users the tools they really need. It doesn't matter to them what the name of the technology behind the scenes is. All they care about is that you have created something that can help them do their jobs better.

Let SharePoint play Clark Kent, so you can look like the super hero.


Dec-132009

SharePoint 2010 - Everything Old is New Again

image "You Must Un-learn what You Have Learned!"

The public beta of SharePoint 2010 has been out for a few weeks now. Many people are discovering and blogging about some of the great new features you're going to find. Yet there have also been some significant changes to existing features. These are things you may have been using every day in SharePoint 2007 and WSS 3.0, but which in SharePoint 2010 have moved or changed in ways could cause confusion to experienced users.

In this article I'm going to focus on changes the typical end-user would see. In future articles I'll talk about changes for site owners and administrators.

If it Ain't Broke…

SharePoint 2007 took a lot of heat for having certain "quirks" in its user interface design. For 2010, much as they did for the Office clients in 2007, Microsoft put a lot of R&D into what it would take to make SharePoint easier for typical users. This resulted in a lot of changes.

Human beings are creatures of habit. With certain notable exceptions, we don't much like change. Despite having worked through a non-intuitive learning curve, or sometimes because of it, we would rather keep doing things the way we are used to than learn new ways - even if those ways are better.

...Fix it Anyway

Only time will tell if the changes Microsoft made truly are for the better, but they've definitely been made. Let's start by looking at the basic team site page in SharePoint 2010 side by side with its SharePoint 2007 equivalent:

image

image

At first glance, they're pretty similar. The WSS logo has been replaced with a "real" picture, but there's still a banner, title area, quick launch, and content space. But look a little closer. The Site Actions menu has moved. No big deal there - lots of custom master pages move that around. But, the new placement is comparable to the Backstage/File menu in the new Office 2010 client applications, thus making it a "natural" place for users to look for "application"(site)-wide functions. This analogy becomes even more obvious when some of the other tabbed interface options start showing up. (You'll see that later in the article.)

Where's MySite?

Another subtle change is the "personal" section of the banner. In SharePoint 2007, you had separate entries for User ID, links, and a direct link to your "My" site.

image

All of these options are now accessed through the menu under your name. There is also no reference to My "Site", rather it simply calls it your "Profile".

image

I think the hope here, is that by de-emphasizing the "independent site" aspect of the profile and personal storage, while actually expanding its function (the new profile features could fill up several articles on their own), resistance to deployment in certain enterprises would be reduced.

Bread-Crumbling Navigation

Getting around from site to site, and from place to place within a site, has received a LOT of attention in SharePoint 2010. In many cases, this has meant "reimagining" the concept of a breadcrumb.

In the case of 2007 site navigation, a breadcrumb stretched across the top of the page content area:

image

For large site hierarchies, this could become unwieldy as it stretched across the page. For 2010, Microsoft replaced it with a folder icon in the tab banner, which produces an indented hierarchical view of your current location:

image

Going the other direction, in SharePoint 2007 lists and libraries selecting a view was accomplished by selecting it from a drop-down list on the toolbar.

image

In SharePoint 2010, there is no list toolbar. While you can drill into the ribbon and find the view settings, then select your view, that's a lot of clicking. Fortunately, Microsoft has turned the title panel into an in-site breadcrumb. When looking at a list or library, the last item in that breadcrumb is the name of the current view. If you look carefully, you'll notice that there is a "down triangle" arrow. That's your hint that this element is actually a dropdown menu, where you'll find all of your view selecting goodness.

image

Tied up with a Ribbon

Of course, the rest of the stuff that used to live on a list or library's toolbar:

image 

has been moved into the Library tab of the new ribbon interface:

image

By the same token, individual items that lived in an individual item's dropdown:

image

have been moved into the Documents (or other appropriate item's) tab:

image

Note: In this case, the individual item dropdown is still there as well.

Summary

Some folks say, "The more things change, the more they stay the same". There have been a lot of changes in SharePoint 2010. While there are some things that have stayed the same, they are actually in the minority. In this article, I have gone over some of the many changes to "carry over" functionality you will find when moving from SharePoint 2007 to SharePoint 2010. There are many more than I could hope to address in a single posting. I hope, however, that this article has given you some ideas of where to look if you can't find your favorite function where it used to be.


Nov-112009

A Free SharePoint Org Chart Web Part

MCj04348220000[1]Enhancing a CodePlex Project

In this article, I'm going to get a bit more technical than is my normal wont. In fact, I'm going to go into Visual Studio, and show you some C# code as well.

(Waiting a few minutes for folks who know me to pick their jaws up off the floor, or even find some smelling salts... Yes, Virginia, I really can program when I have to. :) I just very rarely have to.)

That doesn't mean I'm going to be building this project from scratch. Far from it. So, if you're looking for info on how to build a .wsp solution package, this isn't the article for you. I am going to talk a bit about user choice, web part properties, a programming technique called "recursion", and the SharePoint API (in particular, accessing the User Profile store).

What I'm going to do is show you how to fulfill a very common business requirement by starting with a fairly simple CodePlex project, and tweaking it until it is something that does just what you need.

A Common Request

Virtually every client I've implemented SharePoint for has asked for an organizational chart. The problem is, there aren't very many org chart web parts out there for SharePoint, and those that are, tend to have issues (usually performance) - especially if you have a fairly large organization.

SharePoint Server 2010 finally makes a really cool organization chart part of the package. It is Silverlight based, and works pretty fast. Unfortunately, that's 2010, and it is going to be a while before many companies are ready to deploy it. We need something that will work for "today".

Finding the CodePlex Project

So what do you do? Well, a quick online search reveals that there is indeed an org chart part on CodePlex, called (quite originally) "OrgChartPart". This was written by Rodney Viana. Looking at the specs, it sounds promising:

  • It reads profile information from SharePoint
  • It uses a free JavaScript Org Chart rendering engine
  • And of course, it is free, too!

What's not to like?

There is a bit, as it turns out, but let's start with the good. Installing the OrgChartPart is a breeze. Download the .wsp file from CodePlex, install it with the "stsadm -o addsolution" command, and deploy it to your web application(s). You will then need to add the part to your web part gallery (there is a feature that does this, or you can do it manually), then add it to a page. (I suggest you add it to a web part page that has nothing else on it, for reasons you will see in a moment.) This takes 5 minutes, tops.

The web part reads your MOSS profile store, and emits the chart. Just like that, you're done!

On the surface, that doesn't sound too bad. But dig a little deeper, and you find a big red flag - the author warns that you shouldn't use the part if you have more than 500 profiles in your organization. Of course, if you have more than 500, you've got a problem.

But even if you have fewer than 500 profiles, you might not like the results. Consider the following clip of the chart initially rendered by this part:

image

This is a pretty complicated organization - it doesn't fit on the screen, and it is completely expanded by default. But, there's another issue. The chart looks a little "top heavy". That's because the Active Directory includes a number of accounts that aren't actually users, and therefore don't have associations in the hierarchy. Looking closer, you can see that Patricia Doyle, the CEO, has conference rooms as peers! There's also some clipping of titles and departments.

image

Note: This is technically a problem with the Active Directory and/or its import. In theory, you could set up the AD/Profile import to exclude non-person entities. But, that's another story... :)

Looking Under the Hood

Still, even with those issues, you can see the potential in this part.

Note: Most of the remainder of this article discusses how the OrgChartPart was originally implemented, and how I updated it. If you just want the end results, you can download the original source from CodePlex, plus my replacement OrgChartPart.cs file and rebuild the solution. (I have also given the code updates to Rodney, who may update the actual CodePlex project.)

Fortunately, as with most CodePlex projects, we have access to the source code. I downloaded the source and opened the project in Visual Studio. What we see is, the part is actually quite simple. There is one .cs file (the two in the image below include my edited version, plus the original) and the ECOTree JavaScript library. ECOTree is what actually does the heavy lifting of drawing the chart. By default, OrtChartPart uses just a fraction of the power of this library (follow the link above for more details).

image

There is also a "departmentconfig.xml" file hiding in the Layouts folder of the 12 hive. Hmmm...

Looking at the code itself, we find there are four main functional areas beyond the basics needed to render a web part:

  1. Handling that department file
  2. Crawling the profile store
  3. Building a profile render block
  4. Building the chart

Now, We Tweak

In the rest of this article, I'm going to look at each of the sections I described above, tell you how the original code worked, and show you what I did to update them. While I won't embed the entire source in the article, you can easily download it if you want to examine everything in context.

On the Department File

For now, I'm just going to say that while the idea of mapping the department information in the profile to department home pages is admirable, the way it was implemented was causing some serious performance issues, and would be a long-term maintenance headache. Therefore, I commented out the two lines that actually make use of it (249 and 267 in my updated file), and replaced the link rendering with a simple text rendering. Here are the original and replaced lines from the updated code ( 267, 268).

//this.department = config.Find(EmptyIfNull(Profile[PropertyConstants.Department]));
this.department = EmptyIfNull(Profile[PropertyConstants.Department]);

"config.Find" is part of a config object that is defined elsewhere in the code. For purposes of this article, though, we're just going to ignore it.

Crawling the Profile Store

The profile crawl itself takes place in a function called PopulateOrg(). Examining this routine, a few things stand out.

First, there are two different ways for nodes to be added to the chart. One uses information read from a user's profile, the other feeds static information into a node. (This is used primarily to display an error message, if needed.)

Second, the population routine reads the entire profile store in one fell swoop. Combined with the inefficiency of the department link mapping mentioned above, this is a big part of the performance limiting the part to organizations with 500 or fewer profiles.

Finally, hidden in this routine (but commented out) is a nice little set of sample data.

At its core, an organization is a hierarchy. A hierarchy is made of parents and children. Technically, as long as you know the parent of each node, you can manually construct the organization. This is the approach originally taken by this web part.

foreach (UserProfile pf in pmManager)
{
     Details dt = new Details();
     dt.AddProfile(pf, this.Page.Request);

     if (dt.TrimFullName != String.Empty)
         employeeList.Add(dt);

}

However, a UserProfile object itself has methods for listing its children and ancestors directly. This means that we can easily start at any point in the tree, and generate the organization descendent from it, as well as the chain of command above it.

The ancestors are represented in a single collection, called through the GetManagers() method. The first level of children are just as easily retrieved with the GetDirectReports() method. However, if we want more than one level of child, we would then need to call the GetDirectReports() method for each child returned in the previous call.

If you try doing this with loops, things can get complicated pretty quickly. However, there is a simple way to to handle an arbitrary number of child nodes, to an arbitrary depth. This is a technique called "recursion". Essentially, you create a function that calls itself. In order to keep it from running forever, one of the parameters that should be passed to a recursive function should be a "depth" limiter. Within the function, the child calls decrement this limiter, and stop calling when it reaches a threshold level. In my update, I create the recursive function addChildren(). This takes the starting profile, and the depth limiter as parameters.

protected void addChildren(UserProfile Parent, int levels)
{
    try
    {
        foreach (UserProfile pf in Parent.GetDirectReports())
        { 
           Details dt = new Details();
            dt.AddProfile(pf, this.Page.Request, false);

            if (dt.TrimFullName != String.Empty)
            {
                employeeList.Add(dt);
                if (levels > 0)
                    addChildren(pf, levels - 1);
            }
        }
    }
    catch (Exception ex)
    {
        AddInList("1", "", "Error", "", ex.Message); 
    }
}

Notice also that I have added a parameter to the AddProfile method of the details (dt) object. This third parameter allows me to force the profile being added to act as a root, or top-level, node. (This is used for the management chain of command.)

Giving Your Users Choices

Looking at the stuff I've described in the preceding section, there is something very different from the original implementation - instead of crawling the whole profile store, I crawl a specified subsection. That requires two pieces of input - the node I plan to start with, and how deep I want to crawl.

Fortunately, when you create SharePoint Web parts, you can easily allow the user to enter configuration information. In this case, I am actually going to give the user three options. The third will allow the user to show the sample data instead of the active directory. (Naturally, I uncommented the sample population section, and wrapped the two population methods in an if...else block.)

To add a property to a web part, you add some descriptive information to say how the property is to be displayed. You also set up a public property variable to appear in the configuration pane, and a private variable to use in your code. The private variable can include a default value. The public property includes a get and a set block. While these three properties simply take the value as given, you will see later that this isn't the only option.

[Personalizable(PersonalizationScope.Shared)]
[WebBrowsable(true)]
[System.ComponentModel.Category("Org Chart Settings")]
[WebDisplayName("StartProfile")]
[WebDescription("Enter the top user to display:")]
public string StartProfile
{
    get
    {
        return startProfile;
    }
    set { startProfile = value; }
}
private string startProfile;

[Personalizable(PersonalizationScope.Shared)]
[WebBrowsable(true)]
[System.ComponentModel.Category("Org Chart Settings")]
[WebDisplayName("ChartDepth")]
[WebDescription("Subordinate levels to display:")]
public int ChartDepth
{
    get
    {
        return chartDepth;
    }
    set { chartDepth = value; }
}
private int chartDepth = 1;

[Personalizable(PersonalizationScope.Shared)]
[WebBrowsable(true)]
[System.ComponentModel.Category("Org Chart Settings")]
[WebDisplayName("Show Sample Data")]
[WebDescription("Show sample data instead of profile info:")]
public bool ShowSample
{
    get
    {
        return showSample;
    }
    set { showSample = value; }
}
private bool showSample = true;

This is how the properties look in the Web part configuration pane. The "CacheTime" parameter was included in the original part (though it is unused in the code). I'll discuss the "Left To Right" parameter later.

image

You might also notice that I set the default value of showSample to true. This allows the user to place the web part on the page and see a reasonable representation of its function, without needing to first set the start point and depth.

image 

Note: The chart initially renders with only the first layer of children open. I expanded it for this screen shot.

Rendering a Profile

Each node on the chart is constructed of HTML. The HTML is assembled in the ReturnItem() function.

I wanted to enable two functions not already present - showing the user's profile picture, and allowing the user to "re-home" the chart on another node in order to enable navigation of the entire organization in convenient sections. This meant I needed to add two properties to the details object, and then add the code to display these properties appropriately in the chart.

In order to make the re-home function work, I added an override to the StartProfile. Essentially, if there is a rootuser query string parameter, the profile specified there will be used instead of the one set in the web part property. The SetRoot link calls the current page with rootuser set to the selected profile.

In addition to the actual HTML, however, the look of the node contents are controlled by styles defined in the ECOTree.css file. In order to allow the picture to render, as well as permitting the text to fit, I needed to modify the .econode class in this file as follows.

.econode {
    text-overflow: clip;
    font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
    font-size: xx-small;
        color: White;
    padding: 2px;
}

Rendering the Chart

Just as we built up a node by assembling the HTML, the chart itself is built by assembling JavaScript. One of the things I did was to examine the functions provided by the ECOTree library. I found that it offered a lot of flexibility that wasn't currently in use. I felt the most important was the ability to set the orientation. Here's where that "Left to Right" checkbox comes into play. The library uses a parameter .RO_TOP or RO_LEFT to decide whether the chart is top to bottom, or left to right.

This is the code that reads and sets that web part parameter:

[Personalizable(PersonalizationScope.Shared)]
[WebBrowsable(true)]
[System.ComponentModel.Category("Org Chart Settings")]
[WebDisplayName("Left To Right")]
[WebDescription("Root at left, otherwise at top:")]
public bool RootLeft
{
    get
    {
        if (chartOrient == "LEFT")
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    set
    {
        if (value)
        {
            chartOrient = "LEFT";
        }
        else
        {
            chartOrient = "TOP";
        }
    }
}
private string chartOrient = "TOP";

This demonstrates the kind of things you can do with the get and set blocks of a parameter. The user gets to the see the checkbox that represents a binary choice, but the internal variable is a string, meaning that we can render the part simply appending the string value without inserting an "if" block.

myTree.config.iRootOrientation = ECOTree.RO_");
sb.Append(chartOrient);
sb.Append(@";

The Results

The image below shows you how the revised chart looks with the same profile store shown in the first image.

image

This is a much more manageable presentation. It allows the user to drill into the organization as needed, and since we set the starting node on our CEO, those conference rooms who don't report to anybody are nowhere to be found.

I hope this article has shown you how easy it is to stand upon the shoulders of giants when looking for features to add to SharePoint. I built upon the CodePlex OrgChartPart, which itself leveraged the ECOTree charting library.

There are many more things you could do with this web part. You could add options to select the color of the nodes, for example. Or give users a check-box to render the entire organization at once, as the original part did.

The options are limited only by your imagination!


Oct-272009

SharePoint 2010 Hits the Jackpot

MCj02345130000[1]

SharePoint Conference 2009 Wrap-up

The show is over, but the adventure is only beginning. As stated before, SPC09 in Las Vegas was the coming out party for SharePoint 2010. While we will still have to wait a few weeks for stable bits to play with, over 7000 attendees came away with a treasure trove of knowledge and documentation.

In my previous installments, I talked about the venue, the atmosphere, and the keynotes. I've also touched on some of the new Office integration story.

Of course, the star of the show was SharePoint 2010 itself. So, I'm going to dedicate the rest of this post to a punch-list of changes/improvements. I know I've missed a few (or more than a few) new elements, or misunderstood a detail or two, but even so the list is impressive. You'll see that the SharePoint team at Microsoft have not been resting on their laurels during the three years we've been waiting. Over the next few months, I'll fill in more details on the individual features, correct what I got wrong, or update you on the inevitable feature changes as things get closer to release.

The Basics

It seems Microsoft can't release a new version of SharePoint without tweaking the names a bit. Just as "SharePoint Portal Server" and "SharePoint Team Services" became "Microsoft Office SharePoint Server (MOSS)" and "Windows SharePoint Services (WSS)" in the 2007/3.0 wave, For 2010/4.0, they're simply called "SharePoint Server" and "SharePoint Foundation" respectively.

The Public Beta of SharePoint 2010 is to be released in November 2009.

The actual product release is planned for the first half of 2010.

It is still "SharePoint". Although many weaknesses have been addressed, core functionality remains essentially similar, with lists, libraries, site model, etc... Since "form follows function", many of the visual elements will be very familiar.

Infrastructure and Administration

  • Requires 64bit throughout the stack
  • Windows Server 2008 as a baseline OS
  • Complete redesign of Central Admin
  • Shared Services: No more monolithic "Shared Services Provider". Instead things formerly grouped under an SSP are individual Shared Service Applications.
  • Search architecture changes: index role can be spread across multiple servers
  • "Normal" SharePoint search now scale-tested to around 100 million items.
  • Business Data Catalog transformed into Business Connectivity Services, and becomes part of SharePoint Foundation (no more enterprise CAL required).
  • BCS info becomes available throughout the Office 2010 suite, not just SharePoint, and offers read/write capability.
  • FAST Search is available as an add-on for Enterprise CAL users at per-server pricing.
  • Enterprise-wide metadata support
  • Lists are more scalable, and can be "external" to the SharePoint content database. Admin can set maximum returned items to prevent bogging the system down.
  • Servers can be upgraded without enabling the new UI by default. Site owners can then switch over when their members are ready for the change.
  • AD Group Policies can prevent installation of SharePoint on unapproved systems.
  • Even more databases.
  • Better auditing and reporting in-box.
  • "License" logging to see which features are used.
  • Allowed to read log/report database to build custom reports.

Client Facing

  • UI: No IE6 support for collaboration/team sites. Can still make IE6 friendly publishing sites.
  • Firefox 3.x is a Level 1 browser.
  • "Accessible" CSS-based layouts, and XSLT-based list views.
  • Table-based layouts are gone
  • Cleaner, modernized themes.
  • Ribbons are primary control mechanism, just like Office.
  • There is no longer a separate basic "Wiki" site type in SharePoint Foundation. (However, there is now a publishing-based "Enterprise Wiki" site in SharePoint Server.)
  • All team sites can have wiki functionality enabled, and made the default.
  • Theme colors can be imported from PowerPoint themes for compliance with corporate standards.
  • The GroupBoard template is available out of the box.
  • List lookups can pull multiple fields
  • List lookups support referential integrity (blocking/cascading deletes)
  • Field validation

Social

  • Major overhaul of profiles and My Sites.
  • Includes "status" functionality (i.e. FaceBook/Twitter style updates)
  • Unique org-chart presentation
  • "Folksonomy" to support user-created shared tags in addition to Enterprise "Taxonomy" metadata.
  • Can tag non-SharePoint content

Search (Standard)

  • Improved handling of metadata
  • Faceting (now called "refinement") is built-in
  • Social input to ranking

Search (FAST)

  • All standard SP Search features
  • Deep refinement (polls entire result set to get actual counts)
  • Concept metadata from unstructured content
  • User-role tailored result sets.
  • Massive scalability
  • Superset of standard SP Search API
  • Managed through the same admin UI

SharePoint Designer 2010

  • Complete UI redesign, based on SharePoint "artifacts" rather than file structure.
  • SPD 2010 tied to SP 2010. Will not work on older versions or non-SharePoint sites, and old SPD won’t work against SP 2010 sites.
  • Much better Visual Studio integration – exports Solutions that can be imported into VS for both site designs and workflows.
  • SPD Workflows can be independent of specific lists.
  • SPD Workflows can easily be exported into either Visio 2010 or Visual Studio 2010
  • Finer administrative control over what SPD users can do.
  • Page model is the same, but many changes based on new CSS layouts and Theme engine.

Development

  • The "platform" aspect of SharePoint receives a lot of emphasis with this version
  • Use Visual Studio 2010 for full visual web part design and other SharePoint integration points
  • Can install SharePoint on a client OS (Vista or Windows 7, 64-bit) for dev sandbox.
  • Much better developer documentation out of the gate
  • Client Side object model to make Silverlight controls and web parts easier to develop.
  • REST, ATOM, and other web service interfaces fully supported.

Conclusion

In his keynote and his write-up from a couple weeks ago, Jeff Teper pointed out that the vision and purpose of SharePoint hasn't really changed much from the original 1-page proposal over 10 years ago. Yet the implementation of that vision has grown by leaps and bounds over the succeeding versions. I hope I have shown you that SharePoint 2010 will continue in that tradition. As I said earlier, I'm sure I've missed things. These were just the elements that stuck out as I was going through sessions and reading material. But I have to admit, I'm excited.