Thursday, 15 December 2016

SharePoint Online - Branding with CSS

-----------------------------------------------------------------------------------------
This post is related to a larger group of posts called Migrate SharePoint to Office 365 - Planning & Steps
-----------------------------------------------------------------------------------------

I've gone with a Publishing Site Collection so that I can use the 'Alternate CSS URL' in Site Settings > Master Page.

First off, thanks to the following websites which helped get me started:
Here's what the end result will look like (if you have the same fonts):


Now for the CSS...

/* Design By : Brett Randall */
/*     Design Colours: Greens/Greys/Blues */
/*     Last Modified : 28/02/2017 */
/*     Description: CSS to rebrand SharePoint Online Publishing Site Collection that is using seattle.master */

/* TABLE OF CONTENTS
-- -- -- -- -- -- -- -- -- -- -- -- -- -- --
/* WEB FONTS & STYLES
/* LAYOUT & OVERALL PAGE
/* RIBBON & SUITE BAR
/* HEADER
/* NAVIGATION (TOP NAV BAR)
/* SEARCH
/* NAVIGATION (SIDE NAV/QUICK LAUNCH)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */

/* WEB FONTS & STYLES
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */
@font-face {
  font-family: 'MuseoSans100Regular';
  src: url('../Fonts/museosans_100-webfont.eot'); /* IE9 Compat Modes */
  src: url('../Fonts/museosans_100-webfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
       url('../Fonts/museosans_100-webfont.woff') format('woff'), /* Pretty Modern Browsers */
       url('../Fonts/museosans_100-webfont.ttf')  format('truetype'), /* Safari, Android, iOS */
}

@font-face {
  font-family: 'MuseoSans300Regular';
  src: url('../Fonts/museosans_300-webfont.eot'); /* IE9 Compat Modes */
  src: url('../Fonts/museosans_300-webfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
       url('../Fonts/museosans_300-webfont.woff') format('woff'), /* Pretty Modern Browsers */
       url('../Fonts/museosans_300-webfont.ttf')  format('truetype'), /* Safari, Android, iOS */
}

@font-face {
  font-family: 'MuseoSans500Regular';
  src: url('../Fonts/museosans_500-webfont.eot'); /* IE9 Compat Modes */
  src: url('../Fonts/museosans_500-webfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
       url('../Fonts/museosans_500-webfont.woff') format('woff'), /* Pretty Modern Browsers */
       url('../Fonts/museosans_500-webfont.ttf')  format('truetype'), /* Safari, Android, iOS */
}

.ms-rtestate-field h1 {
    font-size: 39px;
    font-weight:300;
    font-family: MuseoSans300Regular, Arial, "Helvetica Neue", Helvetica, sans-serif;
    line-height: 60px;
    color: #666;
}

.ms-rtestate-field h2 {
    font-size: 24px;
    line-height: 30px;
    font-weight: normal;
    font-family: MuseoSans300Regular, Arial, "Helvetica Neue", Helvetica, sans-serif;
    color: #666;
}

.ms-rtestate-field h3 {
    font-family: MuseoSans300Regular, Arial, "Helvetica Neue", Helvetica, sans-serif;
    font-size: 18px;
    line-height: 30px;
    color: #666;
}

.ms-rtestate-field h4 {
    line-height: 20px;
    font-family: MuseoSans500Regular, Arial, "Helvetica Neue", Helvetica, sans-serif;
    font-size: 14px;
    font-weight: normal;
    font-style: italic;
    color: #666;
}

h1.ms-rteElement-H1B{
  color:#84BD00;
  font-size: 39px;
  font-weight: normal;
  font-family: MuseoSans300Regular, Arial, "Helvetica Neue", Helvetica, sans-serif;
  line-height: 60px;
}

h2.ms-rteElement-H2B {
  color:#FF8F1C;
  font-size: 24px;
  line-height: 30px;
  font-weight: normal;
  font-family: MuseoSans300Regular, Arial, "Helvetica Neue", Helvetica, sans-serif;
}

h3.ms-rteElement-H3B{
  color:#84BD00;
  font-family: MuseoSans300Regular, Arial, "Helvetica Neue", Helvetica, sans-serif;
  font-size: 18px;
  line-height: 30px;
}

h4.ms-rteElement-H4B{
  color:#84BD00;
  line-height: 20px;
  font-family: MuseoSans500Regular, Arial, "Helvetica Neue", Helvetica, sans-serif;
  font-size: 14px;
  font-weight:normal;
  font-style:italic;
}

.ms-rteElement-P{
   color:#666;
}

/* LAYOUT  & OVERALL PAGE
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */

/* Hide unnecessary page elements */
.ms-siteicon-img,  /* Image set as SharePoint site logo in Settings */
.ms-core-listMenu-horizontalBox .ms-listMenu-editLink,  /* Global navigation "Edit Links" when managed navigation is in use */
.ms-core-listMenu-verticalBox .ms-listMenu-editLink,  /* Current navigation "Edit Links" when managed navigation is in use */
#fullscreenmodebox  /* Focus on Content icon */
{
display: none;
}

/* Alter Suite Bar color */
#suiteBarTop > div,
#suiteBarTop #O365_TopMenu {
  background: #333;
}

/* Ensuring a gap between side nav & page content */
#contentBox{
    padding-left:12px;
}

/* RIBBON & SUITE BAR
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */

/* Hide unnecessary page elements */
.o365cs-nav-header16 .o365cs-nav-o365Branding{ display:none !important; } /* O365 Suite Bar - Remove "Office 365" & "SharePoint Text & links */
.o365cs-nav-centerAlign::after{content:"Put Company Slogan Here"; font-size:20px; color:white;line-height: 48px; font-style: italic;} /* O365 Suite Bar - Add Mission Statement */

/* HEADER
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */

/* Add padding to the header area */
#s4-titlerow {
  padding: 10px;
}

/* Site logo wrapper */
#siteIcon {
    margin-right: 0px;
    margin-top: 10px;
}

/* Add new logo image */
.ms-siteicon-a {
    background: #fff url('../Images/siteIcon.png') no-repeat right;  /* Logo image */
    width: 210px; /* Width of logo image */
    max-width: 210px; /* Duplicate the width value */
    height: 52px; /* Height of logo image */
    max-height: 52px; /* Duplicate the height value */
}

/* Wrapper around site logo wrapper */
#titleAreaBox {
    margin: 0;  /* Remove OOTB margin */
}

/* Page title text */
#pageTitle {
    margin-top: 10px;
    margin-left: 12px;
    font-family: MuseoSans300Regular, Arial, "Helvetica Neue", Helvetica, sans-serif;
    font-size: 39px;
    color: #84BD00;
    font-weight: normal;  
}

/* NAVIGATION (TOP NAV BAR)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */

/* Placement & Formatting */
.ms-breadcrumb-top > .ms-core-navigation {
    background: #FFF;
    display: block;
    height: 41px;
    width: 100%;
    text-align: left;
}

.ms-core-listMenu-horizontalBox {
    margin-left: 10px;
}

/* Item text formatting */
.ms-core-listMenu-horizontalBox li.static > .ms-core-listMenu-item {
    background-color: rgb(132, 189, 0);
    height: 16px;
    color: #FFF;
    font-family: MuseoSans300Regular, Arial, Helvetica, freesans, sans-serif;
    font-size: 13px;
    font-weight: normal;
    margin-right: 0;
padding: 10px 10px;
    border: 0px;
    border-right: #FFF 3px solid;
}

/* Hover */
.ms-core-listMenu-horizontalBox li.static > .ms-core-listMenu-item:hover {
    background-color: #999;
    color: #fff;
}
/* Hide the down arrow for drop down nav */
.ms-core-listMenu-horizontalBox .dynamic-children.additional-background{padding-right:0px; background-image: none;}

/* 2nd Level Nav modifications */
ul.dynamic{
    background-color: #666;
    color: #fff;  
    margin-left:3px;
    margin-top:2px;
    padding: 4px 0px;
    border: 0px;
    border-radius: 4px;
    min-width:213px; /* ensures div is as wide as the a{} nav tiles */
}

/* 2nd Level a{} tiles */
ul.dynamic > li.dynamic a{
    background-color: rgb(132, 189, 0);
    width: 190px;
    padding:10px;
    padding-left: 13px;
    color:#fff;
}

ul.dynamic > li.dynamic a:hover{
    color:#fff;
    background-color: #999;
}

/* SEARCH
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */

/* Width of entire Search Box */
.ms-mpSearchBox{
    width: 259px;
    background: rgb(233, 234, 232);
    border-radius:4px;
}

/* Modify default formatting for input */
.ms-srch-sb input {
    width: 187px;
    font-size: 14px;
    color: #000;
}

.ms-srch-sb, .ms-srch-sb:hover{
    padding-top: 5px;
    padding-bottom: 5px;
    background: #fff;
    border: 0px;
    border-radius:4px;
}

#searchInputBox{
    float:left;
    margin: 10px;
}

/* NAVIGATION (SIDE NAV/QUICK LAUNCH)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */

/* Add colour to Quick Launch (side nav bar) */
#sideNavBox{
    background-color: #F4F4F4;
}

.ms-core-listMenu-verticalBox {
    background-color: #F4F4F4;
}

/* Folders/Headings */
.ms-core-listMenu-verticalBox > .ms-core-listMenu-root > li > .ms-navedit-linkNode{
    background: linear-gradient(-90deg, #D7F1F7, #84BD00 );
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#84BD00, endColorstr=#D7F1F7, GradientType=1); /* Gradient workaround for IE9+ */
    font-size:14px;
    padding-left: 10px;
    padding-top: 7px;
    padding-bottom: 7px;
    color: #000;
    font-family: MuseoSans300Regular, Arial, Helvetica, freesans, sans-serif;
    font-weight: normal;
    border-bottom: 1px #F4F4F4 solid;
}

.ms-core-listMenu-item:visited{
    color: #000;
}

.ms-core-listMenu-heading{
    font-weight:bold;
}

li > a.ms-core-listMenu-item.ms-core-listMenu-selected:hover, li > a.ms-core-listMenu-item:hover, .ms-core-listMenu-heading:hover{
    background-color:#999;
    color:#fff;
}

.ms-core-listMenu-verticalBox li.static > ul.static > li.static > .ms-core-listMenu-item{
    padding-top:7px;
    padding-bottom:7px;
    padding-left:20px;
}

li > a.ms-core-listMenu-item.ms-core-listMenu-selected{
    background-color: #84BD00;
    color: #000;
}

.ms-core-listMenu-item, .ms-core-listMenu-item:link{
    color:#000;
}

Friday, 2 December 2016

SharePoint 2010 - Automate Site & Group Creation with Nintex Workflow 2010

What
Nintex Workflow has an action to create a site automatically in SharePoint, but it's functionality is quite limited.  You can't create groups and you can't add staff to those groups.  This tutorial shows you how to create a Nintex workflow to automate the whole process using SharePoint Web Services.

Why
As most SharePoint administrators are aware, it's ALWAYS a bad idea to give staff the ability to create SharePoint sites.  They will end up creating them for the wrong purposes, will not maintain them, no retention policies will get assigned to them, etc.

However, you don't want to restrict your users creative freedom.  You want to govern it in a manageable way.

In order to keep track of all your SharePoint sites, we need to ensure that when we allow staff to create sites/content, it is being properly tagged with the right information.  As long as you are logging & tagging sites with extra data, you can easily govern and manage those sites far into the future.

This tutorial isn't simply how to automate a process that SharePoint already does.  It's automating that process while enforcing that users tag their sites with data that help you manage SharePoint easier.

We are going to use the example of Project Sites.  Project sites have a known lifespan, usually between 1 month & 2 years depending on size.  We want to capture that information so the sites don't hang around for too long.

How
There are 6 steps in my workflow, they are:
  • 1. Set Variables
  • 2. Create Site
  • 3. Create Group
  • 4. Add Group to Site
  • 5. Add Members to Group
  • 6. Send Emails

First:  Create a custom list with the following columns (depending on your needs):

  • Project Name
  • Project Description
  • Department
  • Project Sponsor
  • Project Manager
  • Project #
  • Estimated Completion Date

1. Set Variables
I also created Workflow Variables for my Group Names that had the following naming conventions: {Project Name} - [AccessType]

2. Create Site
Use the following Nintex Action to create a site and add all the data you will collect from your list: Insert Action > Provisioning > Create Site


3. Create Group
Use the following Nintex Action to query a Web Service:  Insert Actoin > Integration > Call Web Service

The image below describes what you need to input into each field to successfully run the AddGroup Web Method within the UserGroup.asmx Web Service.

This will create a group on your Site Collection without access to anything.

4. Add Group to Site
the hard part...

Now we need to give the group access to your newly created site.  Create another Call Web Service Action.

The picture will explain most things, however, to get the PermissionMask value (a value assigned to a permission level like Contribute,Read Only, etc), you need to run the following Powershell script on your server: Retrieve the Permission Mask Values for a Site using Powershell

Once you have that, insert the following information to add the group to your newly created site:
Running the AddPermissions Web Method through the Permissions.asmx web service

5. Add Members to Group
You don't need to do this, but if you're feeling keen you can also run a web service to add a user to the newly created group like this:
running the AddUserToGroup Web Method through the UserGroup.asmx Web Service

6. Send Emails
Of course now you want to send a nice customised email to your user with all the information they need!


Thoughts?
This saves our team so much time, while allowing us to govern site creation and ensure that all sites have metadata tagged against them !

Have you got any cool tricks to help automate governance that you'd like to share?

If you liked this post:

Credit where it's due

SharePoint 2010 - Retrieve the Permission Mask Values for a Site using Powershell

This article stems from another article explaining how to Automate Site & Group Creation with Nintex Workflow 2010

What
Use Powershell to retrieve detailed data about the permission levels on a particular site

Why
I was looking for a way to automate Site & Group creation using nintex workflows.  In order to create groups, you need to call a SharePoint Web Service.  That Web Service requires an input value called 'permissionMask (int)'.

This powershell script will allow you to find the correct permission Mask related to your particular environment & permission levels.

How
Jump onto your WFE, open up SharePoint Powershell as admin and paste in the following code (with the site you wish to retrieve data for:

## Get site permissions using SharePoint 2010 web service in powershell
$uri="http://rootsite/subsite/_vti_bin/Permissions.asmx?wsdl" 
## $siteName is a string which contains the site name for which you need to get the permissions
[String]$siteName="site name"
## $type is a string which contains the object type - List
[String]$type="Web"

## Web Service Reference - http://rootsite/subsite/_vti_bin/Permissions.asmx
$permissionWebServiceReference = New-WebServiceProxy -Uri $uri -UseDefaultCredential 
[System.Xml.XmlNode]$xmlNode=$permissionWebServiceReference.GetPermissionCollection($siteName,$type)

## Creates an GetSitePermissions.xml file in the D:\ which contains the permissions for the site
$output = New-Object -TypeName System.IO.StreamWriter -ArgumentList "C:\temp\GetSitePermissions.xml", $false
$output.WriteLine("<?xml version=""1.0"" encoding=""utf-8"" ?>")
$output.WriteLine($xmlNode.OuterXml)
$output.WriteLine() 
$output.Dispose()

Once the script has run, navigate to C:\Temp and grab the Mask value against the group that has the permissions you want to mimic.


Credit where it's due
Vijai for providing the code: http://www.c-sharpcorner.com/blogs/get-site-permissions-using-sharepoint-2010-web-service-in-powershell