Archive

Posts Tagged ‘Ribbon’

Adding Print capabilities to Project Detail Pages

January 26, 2012 2 comments

A user in the Project Server forums asked a question this week about whether it was possible to add printing capability to the Project Detail Pages in order to allow the ‘forms’ to be printed out as there is no print button available on the ribbon.

Capture1

Out of the box, the printing capability in the Project Web Application is limited to the grids, including the schedule grids that are visible in a schedule PDP and uses a custom page to render the information as can be seen below.

Project Schedule PDP Grid Print

After a little experimenting with the Internet Explorer printing, it seems that PDP’s can be printed quite well directly from the browser, so I thought I would try and pull together a ribbon feature that enables PDP printing.

The feature consists of XML button definition and a little piece of JavaScript to determine if the button will be enabled or not. This is important so that the button can be disabled when the user is on the schedule page that has it’s own grid based printing function like the picture above. For the purposes of this feature, I have gone the quick route and do the check based on the name of the page, in this case if the page is called schedule.aspx the button will be disabled. You may need to modify this check if your schedule based PDP(s) have a different name.

Schedule PDP - Custom Print button disabled

The element.xml looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
	<CustomAction Id="Ribbon.Tabs.PDP.Home.Print"
				  Location="CommandUI.Ribbon">
		<CommandUIExtension>
			<CommandUIDefinitions>
				<CommandUIDefinition Location="Ribbon.Tabs.PDP.Home.Groups._children">
					<Group Id="Ribbon.Tabs.PDP.Home.Print"
						   Sequence="60"
						   Description="Print Custom Group"
						   Title="Share"
						   Command="EnableCustomGroup"
						   Template="Ribbon.Templates.Flexible2">
						<Controls Id="Ribbon.Tabs.PDP.Home.Print.Controls">
							<Button Id="Ribbon.Tabs.PDP.Home.Print.PrintPDP"
									Sequence="40"
									Command="PrintPDP"
									Alt="Print"
									Image16by16="/_layouts/$Resources:core,Language;/images/ps16x16.png"
									Image16by16Top="-96"
									Image16by16Left="-160"
									Image32by32="/_layouts/$Resources:core,Language;/images/ps32x32.png"
									Image32by32Top="-288"
									Image32by32Left="-128"
									LabelText="Print"
									TemplateAlias="o1"
							        ToolTipTitle="Print"
									ToolTipDescription="Print the contents of the PDP"/>
						</Controls>
					</Group>
				</CommandUIDefinition>
				<CommandUIDefinition Location="Ribbon.Tabs.PDP.Home.Scaling._children">
					<MaxSize
						Id="Ribbon.Tabs.PDP.Home.Scaling.Print"
						Sequence="140"
						GroupId="Ribbon.Tabs.PDP.Home.Print"
						Size="LargeLarge"/>
				</CommandUIDefinition>
			</CommandUIDefinitions>
			<CommandUIHandlers>
				<CommandUIHandler Command="EnableCustomGroup"
								  CommandAction="javascript:return true;" />
				<CommandUIHandler Command="PrintPDP"
								  CommandAction="javascript:window.print();"
								  EnabledScript="javascript:
								  function disablePrintForSchedule() {
									var sPath = window.location.pathname;
									var sPage = sPath.substring(sPath.lastIndexOf('/') + 1);
									if (sPage.toLowerCase() == 'schedule.aspx')
									{
										return false;
									}
									else
									{
										return true;
									}
								   }
									disablePrintForSchedule();"
/>
			</CommandUIHandlers>
		</CommandUIExtension>
	</CustomAction>
</Elements>

The process of building the feature is exactly the same as outlined in http://epmsource.com/2011/12/13/hiding-disabling-ribbon-items-in-project-server-part-ii/ but substitute the above code into the Element.xml file and change the feature name accordingly.

Once the feature is deployed and activated a Print button should available on the PDP ribbon that when clicked will invoke the Internet Explorer print dialog.

PDP Print Button

From my preliminary testing, the output is pretty good, as can be seen from this ‘Print to XPS’ below:

XPS Printer Output

I have uploaded the full source to Skydrive which can be downloaded from the link below.

Project PDP Print Page

Happy PDP printing Smile

Hiding & Disabling ribbon items in Project Server, Part II

December 13, 2011 1 comment

In the last post, we covered a few things you will need to know when hiding or disabling ribbon buttons in PWA. In this post we will look at how to actually hide the buttons.

Where to start?

Irrespective of whether you wish to hide or disable a button in the ribbon, you will need to follow the same basic process by building a solution in Visual Studio that will deploy your ribbon customisation.

To start, open up Visual Studio and choose to create an Empty SharePoint Project.

Create Empty SharePoint Project

Enter a name and then click on OK. You will then see the SharePoint Customisation Wizard, enter the local site you wish to use for debugging and choose to ‘Deploy as a sandboxed solution’.
SharePoint Customisation Wizard

On clicking finish, Visual Studio will create a solution ready to be customised.

To start with we need to create a feature,  this is a logical container for our customisation and allows the user to turn on and off the customisation by activating and deactivating the feature. To do so, right click on Features in the solution explorer and choose Add Feature.

Add Feature

A feature will be created and Visual Studio will show a page where you can enter information about the feature such as the name, description and the scope. In this case we are going to choose Web (for an individual site) as we want this change to deploy only to the /PWA site and not all the children sites.

Hidebutton Feature

Next we want to add an element to the solution, this is where the real work is done and contains the XML that will be used to configure our ribbon.

To add an element, right click on the project name, choose Add, New Item

Add New Item

In the dialog that is displayed, scroll down and select Empty Element and give it a name.

Add Element

Once you click add, the element will be created.

Blank Element

Now the empty element is created, all that is needed is to add the relevant XML to either disable or remove the button.

Disabling a button

For this example, we shall be disabling the EPT Change button from the Project Centre ribbon. To do so we need to know the ID of the item as defined in the ribbon so we can build up some XML that defines what we want to do to that item. To find the ID, we need to look through the PWARibbon.xml file, which can be a bit daunting, but after a while you will understand the structure and finding the Id’s will become simple.

SharePoint ribbon customisations use a defined XML schema which describes the structure and behaviour of the ribbon and the items that make it up. In order to disable the EPT Change button, we need to override the current structure and behaviour to change the configuration of what the button will do, in this case, pointing to a command that doesn’t exist.  In doing so, the ribbon will disable the button for us, giving us the desired effect.

To get the various attributes of the button, the PWARibbon.XML is your friend, containing all the configuration information you will need. In this case I have taken the configuration of the button and changed the command to point at a non existent command, which will cause the button to be disabled. This XML then needs to be put in the Element.xml file ready to be built, but more on that later.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
	<CustomAction
			Id="Ribbon.ContextualTabs.ProjectCenter.Home.ChangeProjectType.Change"
			Location="CommandUI.Ribbon"
			Title="Disables the EPT Change button in the Project Center Ribbon">
		<CommandUIExtension>
			<CommandUIDefinitions>
				<CommandUIDefinition Location="Ribbon.ContextualTabs.ProjectCenter.Home.ChangeProjectType.Change">
					<Button
						Id="Ribbon.ContextualTabs.ProjectCenter.Home.ChangeProjectType.Change"
						Command="ChangeReplacement"
						Sequence="10"
						Image16by16="/_layouts/$Resources:core,Language;/images/ps16x16.png"
						Image16by16Top="-112"
						Image16by16Left="-190"
						Image32by32="/_layouts/$Resources:core,Language;/images/ps32x32.png"
						Image32by32Top="-352"
						Image32by32Left="-96"
						LabelText="$Resources:pwafeatures,WEBPARTS_PROJECTCENTERPART_CM_CHANGE"
						TemplateAlias="o1"
						ToolTipTitle="$Resources:pwafeatures,PAGE_PDP_CM_CHANGE_WORKFLOW"
						ToolTipDescription="$Resources:pwafeatures,SUPER_TOOLTIP_CHANGE_PROJECT_TYPE"
						/>
				</CommandUIDefinition>
			</CommandUIDefinitions>
		</CommandUIExtension>
	</CustomAction>
</Elements>

Removing a button

The XML code required to remove a button is simpler. Instead of defining the XML for the whole button, all that is required is to redefine the CommandUIDefinition as per below.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
	<CustomAction
			Id="Ribbon.ContextualTabs.ProjectCenter.Home.ChangeProjectType.Change"
			Location="CommandUI.Ribbon">
		<CommandUIExtension>
			<CommandUIDefinitions>
				<CommandUIDefinition Location="Ribbon.ContextualTabs.ProjectCenter.Home.ChangeProjectType.Change" />
			</CommandUIDefinitions>
		</CommandUIExtension>
	</CustomAction>
</Elements>

When PWA parses the XML it uses this to remove the button as key items are not defined. Once again, all that is required to remove the button is to move this XML into the Elements.XML file and save ready for building.

In both cases, if you wish to hide or disable more than one button, you will need to duplicate the Custom Action mark up and change as necessary for each button.

How to Build

Finally once the configuration is completed, all that is required is to build and deploy the solution. To do so, right click on the project name and choose build, if everything is ok, you should see something similar to this in the build output:

Build Succeeded

If the build fails, then there may be a problem in your code. I have packaged the code up I used to build this post into a zip file which is available from my Skydrive account so you can compare or copy.

Once the build is successful you can deploy the solution by right clicking on the solution name and choosing deploy. VS 2010 will then deploy the solution to the site you entered for debugging and activate the solution in the site collection.

Activate Feature

Once the solution has been activated, you should see the changes to the ribbon in Project Center.

As you can see from above, creating a custom feature to hide or disabling buttons in the ribbon is relatively simple once you have the basic structure in place. Hopefully this post has explained how to build these customisations for use in your next project or internal implementation.

Hiding & Disabling ribbon items in Project Server, Part I

December 7, 2011 Leave a comment

Recently I have been working on a number of projects where the requirement to disable ribbon commands in Project Server has come up again and again. There are a couple of posts out there around modifying the ribbon, but they tend to focus on adding new items, not removing or disabling them, so I thought I would post something covering it. Of course, before you look at disabling the ribbon item through a customisation, you should look to see if the item can be disabled using the Project Server security model first.

What you need to know about the ribbon

If you are going to do any work on the ribbon, you need to be aware of a couple of things, firstly for performance reasons the ribbon is cached client side, which makes it really really painful to work with as your changes may not be visible straight away. To get around this, I found using the InPrivate mode of Internet Explorer stopped the client side caching and ensured my ribbon changes were visible.

Secondly, if you are going to hide or disable a ribbon item you need to know the ID of the item. Both SharePoint and Project Server have xml configuration files that define the structure of the ribbons, for SharePoint the ribbon structure is defined in a number of files, but the main one is CMDUI.XML located in {SharePointRoot}TEMPLATE\GLOBAL\XML\CMDUI.XML. For Project Server, the ribbon definitions are kept in the PWACONFIG.XML file located in C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\FEATURES\PWARibbon\listtemplates. The file itself contains the configuration of each button within the PWA app, including the name, image, command to be fired when clicked and references to the tooltips etc.

Example of PWACONFIG.XML

Finally, in the case of Project Server, you need to make sure you find the correct Id, things like the Timesheet ribbon have different id’s depending on whether the timesheet is running in Single Entry Mode, or normal timesheet mode.

To disable or hide? That is the question…

There are two schools of thought when disabling commands in SharePoint and therefore Project Server, to disable or hide the buttons. Hiding the buttons will remove the button completely from the ribbon, whereas disabling the button will leave the button on the ribbon, but in a state that cannot be clicked, thus stopping the functionality the item provides.

Normal Normal Ribbon
Disabled Disabled button on ribbon
Hidden Hidden button on ribbon

 

As you can see from above, the disabling route will be less confusing and will lead to a more consistent user experience for end users, but there are still situations where hiding might be the best route to go (I have a couple of customers that preferred hiding to disabling).

In the next post, we will look at how hide and disable a button using Visual Studio and some SharePoint features.

Invoke Project Status reporting, direct from the ribbon

January 31, 2011 5 comments

Over the past few weeks I have been working on a number of projects that required the Project Server ribbon to be customised in one way or another. During one of these, I started to wonder how simple it would be to integrate a Reporting Services report into the ribbon, specifically a Project Status Report.

Project Ribbon with Status report button

It turns out the answer is very simple, so read on Smile

Before I get into the nuts and bolts, I should say that for this post I am not going to reinvent the wheel, instead I am going to leverage the Project Status report that ships as part of the Project Server 2010 Demonstration and Evaluation pack.

Project Status Report

As you can see, the report is pretty full featured, leveraging all the advanced visualisation features that Reporting Services can provide.

Before we hook the report up to the button, there are two problems that need to be solved:

    How to determine which project to run the report for?

The Project Status report requires a ProjectUID in order to determine which project information to display in the report. Luckily Project Server uses ProjectUID as a parameter to tell the various PDP pages which project data should be displayed and passes it through as a query string.

ProjectUID in Query string

If we access this query string value using some Javascript, we will know the project context to pass to the report.

How to pass the parameter to the report?

In my environment, Reporting Services has been configured to use SharePoint Integrated Mode, which makes it really easy to use a special query string to run the report.Reporting Services integrated mode

In my case, the following query will run the report.

http://project.contoso.com/PWA/_layouts/ReportServer/RSViewerPage.aspx?rv:RelativeReportUrl=/PWA/Reporting%20Services%20Reports/ProjectStatusReport.rdl& rv:ParamMode=Collapsed&rp:ProjectUID=’1c7ca65a-3505-4570-9b65-24633063e9ae’

There are a couple of things to take note of, the rv:ParamMode=Collapsed makes sure that the parameter area is collapsed in the report, which can take up a large amount of space otherwise. The rp:ProjectUID=’1c7ca65a-3505-4570-9b65-24633063e9ae’ passes the ProjectUID parameter and GUID into the report. There are a few other configuration parameters that can be passed through, outlined in this excellent blog post.

Now that both problems are solved, all that is needed is to crack open Visual Studio 2010 and wire up a SharePoint feature that will create a custom ‘Status Report’ button on the ribbon and then when clicked read the ProjectUID from the query string and use that to kick off the status report.

Customising the Project ribbon

Customising a ribbon in Project Server is pretty simple.  Just before Christmas, Jim Corbin posted an excellent article covering the nuts and bolts of this much better than I could and in the last few weeks Andrew Connell has published an article on MSDN covering the ribbon in extreme detail. For this project, we need to customise the ribbon to do a couple of things:

  • Create a new group on the PDP ribbon tab called ‘Reporting’
  • Add a new button to the group called ‘Status Report’
  • Define a custom image to be displayed on the Status Report button
  • Wire the button up to run some JavaScript that will pull in the query string and run the report.

    The XML below achieves all of this:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
	<CustomAction Id="Ribbon.Library.Actions.Scripts"
                Location="ScriptLink"
                ScriptSrc="ProjectRibbonStatusReport/ProjectStatusReport.js" />
	<CustomAction Id="Ribbon.Tabs.PDP.Home.Reporting"
				  Location="CommandUI.Ribbon">
		<CommandUIExtension>
			<CommandUIDefinitions>
				<CommandUIDefinition Location="Ribbon.Tabs.PDP.Home.Groups._children">
					<Group Id="Ribbon.Tabs.PDP.Home.Reporting"
						   Sequence="60"
						   Description="Reporting Custom Group"
						   Title="Reporting"
						   Command="EnableCustomGroup"
						   Template="Ribbon.Templates.Flexible2">
						<Controls Id="Ribbon.Tabs.PDP.Home.Reporting.Controls">
							<Button Id="Ribbon.Tabs.PDP.Home.Reporting.RunStatusReport"
									Sequence="40"
									Command="RunStatusReport"
									LabelText="Status Report"
									Alt="Status Report"
									ToolTipTitle="Project Status Report"
									ToolTipDescription="Run the Project Status report for the current project."
									Image16by16="/_layouts/images/ProjectRibbonStatusReport/Report_16x16.png"
									Image32by32="/_layouts/images/ProjectRibbonStatusReport/Report_32x32.png"
									TemplateAlias="o1" />
						</Controls>
					</Group>
				</CommandUIDefinition>
				<CommandUIDefinition Location="Ribbon.Tabs.PDP.Home.Scaling._children">
					<MaxSize
						Id="Ribbon.Tabs.PDP.Home.Scaling.Reporting"
						Sequence="140"
						GroupId="Ribbon.Tabs.PDP.Home.Reporting"
						Size="LargeLarge"/>
				</CommandUIDefinition>
			</CommandUIDefinitions>
			<CommandUIHandlers>
				<CommandUIHandler Command="EnableCustomGroup"
								  CommandAction="javascript:return true;" />
				<CommandUIHandler Command="RunStatusReport"
								  CommandAction="javascript:runStatusReport();" />
			</CommandUIHandlers>
		</CommandUIExtension>
	</CustomAction>
</Elements>

Now there is one final caveat, the button isn’t security trimmed, so if you have access to the PDP, you will have access to the button, bare this in mind if you are planning to implement.

Running the code

As defined in the ribbon XML above, when the button is pressed, the runStatusReport() method will be invoked, which will call the Javascript code below to read the query string value for ‘projuid’, pass it into our URL and then open a popup window containing the Project Status report. Now this JavaScript doesn’t validate the content of the query string being read for potential hacks and you may want to look at that before deploying it to your production environment, but it gives you a pattern for implementation.

function getQuerystring(name) {
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp(regexS);
var url = window.location.href;
var lowercaseurl = url.toLowerCase();
var results = regex.exec(lowercaseurl);
 if( results == null ) return "";
else return decodeURIComponent(results[1].replace(/\+/g, " ")); }

function OpenPopup (c) {
window.open(c, 'window', 'width=800,height=680,scrollbars=yes,status=yes');
 }

function runStatusReport() {
var ProjectUID = getQuerystring('projuid');
var URLString = 'http://project.contoso.com/PWA/_layouts/ReportServer/RSViewerPage.aspx?rv:RelativeReportUrl=/PWA/Reporting%20Services%20Reports/ProjectStatusReport.rdl&rv:ParamMode=Collapsed&rp:ProjectUID=' + ProjectUID;
OpenPopup(URLString);
}

In order to deploy this ribbon customisation and JavaScript into PWA, a feature needs to be built that will move the various files into the correct location on the server and activate the feature. Instead of walking through the process of building the feature, I have decided to make the Visual Studio 2010 solution available for download from my Skydrive account by clicking on the icon or link below.
Project Ribbon Status Report SolutionDownload

Finally, once installed and activated, a new Reporting group will be added to the Project ribbon with a Status Report button that when clicked will invoke a popup window containing the relevant Project Status Report.

The final report

Hopefully this has give you an insight into what is possible and sparked off some ideas of how to integrate other items into the ribbon to bring more value to users.

Follow

Get every new post delivered to your Inbox.

Join 234 other followers