Saturday, November 14, 2009

Updating content type's and site column's group name using PowerShell

Few hours before deploying a SharePoint site I figured out that the group name of my Content Types and also the Site Columns are spelled incorrectly. I don’t want to delete and recreate neither the content types nor the site columns. So the options are: write console application that change the titles and run it on the server, or to make the same using PowerShell. And here are the steps to do it using PowerShell:

Making backup from your site is recommended.

1. First you need to have PowerShell installed on your server.
2. From the CMD, type Powershell then Enter
3. Import the SharePoint Assembly by typing [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

4. Create a site object from your site where the columns and the content types
$site = new-object Microsoft.SharePoint.SPSite(“http://cairo:4000”);

6. Update the Content Type group title
$site.rootweb.contenttypes[“TheContentTypeName”].Group = “TheNewGroupTitle”; $site.rootweb.contenttypes[“TheContentTypeName”].Update($true,$true);

8. Update the Site Column group title
$site.rootweb.Fields[“TheColumnName”].Group = “TheNewGroupTitle”; $site.rootweb.Fields[“TheColumnName”].Update();

10. Exit PowerShell
11. Test the related modules.

Wednesday, November 11, 2009

Silverlight Organization Chart - Part 3 - The Node

Now after we talked about retrieving the data from the XML file, and calculating the nodes positions, we need to talk about drawing and the first thing that we need to draw is the node itself.

In this post, please note that I’m using the “Silverlight Hebrew & Arabic Language Support” library.

My XAML file will look like that:

<UserControl xmlns:my="clr-namespace:System.Windows.BidiControls;assembly=BidiControls" xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input" x:Class="OrgChart.NodeBox"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Width="140" Height="80">

<Canvas x:Name="canvMain" MouseEnter="canvMain_MouseEnter" MouseLeave="canvMain_MouseLeave">

<Rectangle x:Name="recBorder" RadiusX="5" RadiusY="5" Stroke="CornflowerBlue" StrokeThickness="2">

<Rectangle.Fill>

<SolidColorBrush Color='#f2f3fd' />

</Rectangle.Fill>

</Rectangle>

<my:TextBlock TextAlignment="left" x:Name="tbEmployeeName" Width="130" Height="20" Foreground="Black" Canvas.Left="5" FontWeight="Bold"></my:TextBlock>

<my:TextBlock TextAlignment="left" x:Name="tbTitle" Width="130" Height="20" Foreground="Black" Canvas.Left="5"></my:TextBlock>

<my:TextBlock TextAlignment="left" x:Name="tbDepartment" Width="130" Height="20" Foreground="Black" Canvas.Left="5"></my:TextBlock>

<my:TextBlock TextAlignment="left" x:Name="tbExtension" Width="130" Height="20" Foreground="Black" Canvas.Left="5"></my:TextBlock>

<Canvas.Resources>

<Storyboard x:Name="mouseEnter">

<ColorAnimation

Duration='00:00:01'

To='#ffffcc'

Storyboard.TargetName='recBorder'

Storyboard.TargetProperty='(Shape.Fill).(SolidColorBrush.Color)' />

</Storyboard>

<Storyboard x:Name='mouseLeave'>

<ColorAnimation

Duration='00:00:00'

To='#f2f3fd'

Storyboard.TargetName='recBorder'

Storyboard.TargetProperty='(Shape.Fill).(SolidColorBrush.Color)' />

</Storyboard>

</Canvas.Resources>

</Canvas>



Where you will find a reference to the BidiControls for the Arabic support, a canvas with a border and four TextBlock to display the Name, Title, Department and the Extension and the values are assigned from the properties in the code behind.
Also there are two storyboards to change the background color on mouse hover.

The code behind will look like that:

namespace OrgChart

{

public partial class NodeBox : UserControl

{

private double _fontSize = 10;

public NodeBox(double scale)

{

_Scale = scale;

InitializeComponent();

tbEmployeeName.FontSize = _fontSize * Scale;

tbEmployeeName.SetValue(Canvas.TopProperty, 5 * scale);

tbEmployeeName.SetValue(Canvas.LeftProperty, 5 * scale);

tbEmployeeName.Height = 20 * scale;

tbEmployeeName.Width = 130 * scale;

tbEmployeeName.TextWrapping = TextWrapping.NoWrap;

tbEmployeeName.Clip = new RectangleGeometry() { Rect = new Rect(0, 0, 130 * scale, 20 * scale) };

// the same for all the controls on the canvas

}

// Control Properties to set the TextBlock Values

}

}



Where font size, width, height, the location and the clip area of each TextBlock must be adjusted based on the scale. Also the node border must be adjusted, the rounded corner radius and the thikness and the dimentions:

recBorder.StrokeThickness = 2 * scale;

recBorder.RadiusX = 5 * scale;

recBorder.RadiusY = 5 * scale;

recBorder.Width = this.Width * scale;

recBorder.Height = this.Height * scale;



Our next step will talk about drawing the nodes and the lines on the main control.

Sunday, November 01, 2009

Backup with DateTime

Want to make a batch file that is making backup to your SharePoint site and add to the file name a date? or add also the time?

Use this command in your batch file:

stsadm -o backup -url http://siteurl -filename sitename%date:~-4,4%%date:~-10,2%%date:~-7,2%-%time:~0,2%%time:~3,2%.dat

This will make the command as:
stsadm -o backup -url http://siteurl -filename sitename20091101-1159.dat

Where: 20091101 is the date yyyymmdd, and 1159 is HHMM

Update: running this script before 12 PM will render with space not a zero, so add these lines

SET T=%time:~0,2%%time:~3,2%
SET T=%T: =%

which will replace the empty space

stsadm -o backup -url http://siteurl -filename sitename%date:~-4,4%%date:~-10,2%%date:~-7,2%-%T%.dat

Silverlight Organization Chart – Part 2 – Calculations

Now we have the nodes list ready from the previous post, the second step is to start calculating where each node will be displayed. The below points will be called while loading the first time and then when the user resize the chart or open and close any node. For sure it will be better to just draw the chart with the new scale on resizing. And I’ll work on it to enhance its performance isA.


Point 1: Prepare the data


In this point we will start with the root node, and go to the child nodes then the sub child and so on. We need to set the level for each node, and the number of opened and closed sub nodes, also we will set the sub nodes order and the default allowed width for the second level. Also the total height will be calculated.

private void SetLevel(Person parent, int level)

        {

            // Set the node level

            parent.Level = level;

 

            // Calculate the total height based on the number of levels

            if (totalHight < levelHight * (level + 2))

            {

                totalHight = levelHight * (level + 2) ;

                MyCanvas.Height = totalHight;

            }

 

            // Select the closed items under this parent

            var resultN = from n in persons

                          where n.ManagerID == parent.ID && n.Opened == false

                         select n;

 

            Person[] nodesN = resultN.ToArray();

 

            // Get the closed nodes number

            parent.HiddenSubNodes = nodesN.Length;

 

            // Select the opend nodes under this parent

            var result = from n in persons

                         where n.ManagerID == parent.ID && n.Opened == true

                         select n;

 

            Person[] nodes = result.ToArray();

 

            // Get the Opend nodes number

            parent.SubNodes = nodes.Length;

 

            // Call the child nodes

            for (int i = 0; i < nodes.Length; i++)

            {

                nodes[i].NodeOrder = i + 1;

                nodes[i].MinChildWidth = buttonWidth + minHorizontalSpace;

                SetLevel(nodes[i], parent.Level + 1);

            }           

        }



Point 2: Calculations


In this point we will need to:
1. Calculate the width for each node based on the opened sub nodes. As you can see in the image, the minChildWidth for the blue node is not the same as the default.
2. Calculate the StartX for each parent node.
3. Calculate the X coordinate for each node based on the StartX of the parent and the node order.
4. Realign the parent node to be centered in the space allowed for its sub nodes.

private void CalculateWidth(Person parent)

        {

            if (parent.SubNodes > 0)

            {

                var result = from n in persons

                             where n.ManagerID == parent.ID && n.Opened == true

                             orderby n.NodeOrder

                             select n;

 

                Person[] nodes = result.ToArray();

                double minWidth = 0;

                for (int i = 0; i < nodes.Length; i++)

                {

                    CalculateWidth(nodes[i]);

                    minWidth = minWidth + nodes[i].MinChildWidth;

                }

 

                if (minWidth > parent.MinChildWidth)

                {

                    parent.MinChildWidth = minWidth;

                    if (MyCanvas.Width < minWidth)

                    {

                        MyCanvas.Width = minWidth;

                        totalWidth = minWidth;

                    }

                }

 

                // Calculate the startX for each node

                double start = parent.StartX;

                for (int i = 0; i < nodes.Length; i++)

                {

                    nodes[i].StartX = start;

                    nodes[i].X = nodes[i].StartX + nodes[i].MinChildWidth / 2;

                    CalculateWidth(nodes[i]);

                    start = start + nodes[i].MinChildWidth;

                }

 

                // realign the parent node to the middle of the child nodes

                if (nodes.Length > 1)

                {

                    parent.X = (nodes[0].X + nodes[nodes.Length - 1].X) / 2;

                }

                else // root element

                {

                    parent.X = nodes[0].X;

                }

            }

        }



After that we will just need to draw the nodes, we have the X coordinate and we have the Y Coordinate with can be calculated from the level multiplied by the level hight.