segunda-feira, Novembro 24, 2014

How to add current SharePoint installed Apps in new App Launcher Office 365

Ok the new App Launcher is live but i already see missing one functionality such as list the existing installed apps in the current SharePoint site.
The Out of the box way to get this Lists of Apps in the current site is accessing the option Site Content in the Site Options menu in the top Rigth.
This article explain how you can create a JS and inject your current Installed Apps in the App Launcher on your Office 365 Site.

This method try to be very evasive in current site and untouch Other Sharepoint Sites and Other Office 365 Shell, only try to response and displays installed Apps in a nice Look and Feel using the new existing option in this case the App Launcher.

Here the final output, the List os installed apps in my current site in the App Launcher:


If a Site administrator wants to visualize the current Installed app you need to access to site Content Apps and start to search one by one, the code created filter the installed Apps from Out of the box app, yes everything is a App....



Inject current installed Apps in the App Launcher 

This code was created to List all Installed apps in Current Site and include in App Launcher using JQuery .

Code Example:

var appinstancesList;
var clientcontext;
var currentWeb;
 
LoadApps();
$('body').append('<script>window.onhashchange = locationHashChanged;function locationHashChanged(){LoadAppsMDS();}</script>');
function LoadApps() {
    $(document).ready(function () {
        LoadAppsMDS();
    });
}
 
function LoadAppsMDS() {
    clientcontext = SP.ClientContext.get_current()
    currentWeb = clientcontext.get_web();
    appinstancesList = SP.AppCatalog.getAppInstances(clientcontext, currentWeb);
    clientcontext.load(appinstancesList);
    clientcontext.executeQueryAsync(Success, fail);
}
 
function Success() {
    var stringHtml = '';
    var list = appinstancesList.getEnumerator();
    while (list.moveNext()) {
        var current = list.get_current();
 
        stringHtml += '<div class="o365cs-nav-appItem"><a class="o365cs-nav-appTile o365button o365cs-nav-appTileMedium" id="O365_AppTile_Admin" role="link" aria-disabled="false" style="outline-color: rgb(0, 114, 198); background-color: rgb(0, 114, 198);" aria-label="Admin" href="/_layouts/15/appredirect.aspx?instance_id={' + current.get_id() + '}"><span class="o365cs-nav-appTileIcon owaimg wf wf-size-x22 wf-o365-office365adminlogo wf-family-o365 ms-fcl-w" role="presentation"></span><img class="o365cs-nav-appTileImage" style="display: none;" aria-label="Admin" src="/_layouts/15/images/ltgen.gif?rev=38"><span class="o365cs-nav-appTileTitle ms-fcl-w">' + current.get_title() + '</span><button class="o365cs-nav-appAffordance ms-fcl-w o365button" aria-haspopup="true" aria-label="Open the context menu to pin, unpin, and resize" type="button"><span class="o365cs-nav-appAffordanceIcon owaimg wf wf-size-x12 wf-o365-ellipsis wf-family-o365" role="presentation"></span></button></a></div>';
    }
    $("#O365_MainLink_NavMenu").click(function () {
        $(".o365cs-nav-appItem").parent().append(stringHtml);
        $("#O365_MainLink_NavMenu").unbind();
    });
}
function fail(sender, args) {
    alert(args.get_message());
}



Upload the JS file to a Library in your sharePoint Site for this example uploaded to Library SiteAssets. 




After the File is added to your SharePoint site you are able to add a Scriplink to your SharePoint Site, can be done using JSOM.
Example:
"How to include User Custom Actions and Scriptlink using SharePoint JSOM"
http://aaclage.blogspot.ch/2013/12/how-to-include-user-custom-actions-and.html
for this example i use the app 
"Processlynx Custom Action and Ribbon Manager"
http://aaclage.blogspot.ch/2014/06/sharepoint-app-processlynx-custom.html


If you like to use Visual Studio and Declarative code you can use the option "Generate Declarative XML" to create the XML for your SharePoint Feature as shown.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction Id="AddwebAppsOpenLauncher" Title="AddwebAppsOpenLauncher" Description="" Location="ScriptLink"ScriptSrc="~Site/SiteAssets/AddWebAppsOpenLauncher.js" Sequence="2" > </CustomAction>
</Elements>

After you upload your Custom JS file add the Scriptlink to your Office 365 Site to Jquery added to your sharePoint Site and give sequence as 1.


After the Jquery reference Scriptlink is added your can make the reference to Custom JS File with a sequence bigger then given to Jquery.



After the Scriptlink is created access to your SharePoint and open again your App Launcher and your are able to see the Installed Apps in your current Site, becaming more easy to acces your Apps.



Done, easy to visualize your current Installed Apps, this is a 5 minute code, didn't take to much care about Image and reorder the App in the App Launcher.

This script isn't inclued in all Office 365 enviroment just the site your have injected the Javascript and can be access by scope Site Collection or Web.

Hope you like this article,
Kind regards, 
André Lage

sexta-feira, Novembro 21, 2014

SharePoint Hosted App: How to manage DateTimeControl Picker and Format with the correct Language and Culture

This article explains how convert the Raw Date from REST calls and manage Date Format base in different Languages and lcid and how to manipulate the Out of the Box SharePoint Control  DateTimeControl to display the correct Language in the DatePicker with the correct Date Format.  
This is very important when you are creating your App with multiple Languagues and you need to keep integrity of Regional settings bettwen your Hosted site and App Web Site and have to be done in dinamyc approach.

DateFormat SharePoint Hosted App example 

Let's go for steps:
  • Create a Site and define his Language
    • For this example a Site Collection was created base in Language "PT-pt" and Lcid 2070



Create a SharePoint Hosted App call "DateFormat", this solution shows the tips and trick about managing Dateformats, Culture and Languages using out of the box SharePoint controls and Raw dates from SharePoint Data.


Add DateTimeControl in App


Include the SharePoint Web control Markup DateTimeControl in the default.aspx Page.

When the SharePoint Hosted App is installed in the SharePoint Site access the App Web select the calendar Picker,
Since you create your Host site base in Language "PT-pt" and Lcid "2070" you are expecting to get the correct Language, but that don't happen like is shown in the image bellow.

PS:"The control has a LocaleId parameter but i dont include in the Control since the language can change and don't have access to server side code, everything should be made using JS"

If you access to F12 Developer tools you are able to see that the DatePicker control opens a iframe base in Parameters but the most interresting are the values from there, 
  • lcid: 1033
  • Langid:2070 


This is the reason the calendar appear with En-US Language in the calendar and not with PT-pt language, 

To get the correct values from the iframe parameter you can use the Regional Settings of the current Web.

For more information about the parameter see the 3 point "Calendar Options" in the following article, 
Using SharePoint’s DatePicker Control:

You can use REST call fill the needed parameters in the datepicker Iframe request.



Thef following code example call the Regional Settings and replace the parameters that i used in the Calendar picker with the lcid "1033" to correct lcid, for this case "2070":

$.ajax({
      url: getQueryStringParameter("SPAppWebUrl") + "/_api/Web/RegionalSettings",
      method: "GET",
      headers: { "Accept""application/json; odata=verbose" },
      success: function (data) {
          $(".ms-dtinput a").each(function () {
              $(this).attr("onclick", $(this).attr("onclick")
                  .replace(/cal=\d{1,2}/"cal=" + data.d.CalendarType)
                  .replace(/lcid=\d{4}/"lcid=" + data.d.LocaleId)
                  .replace(/ww=\d{7}/"ww=" + ("0000000" + data.d.WorkDays.toString(2)).slice(-7))
                  .replace(/fdow=\d{1}/"fdow=" + data.d.FirstDayOfWeek)
                  .replace(/fwoy=\d{1}/"fwoy=" + data.d.FirstWeekOfYear)
                  .replace(/hj=\d+/"hj=" + data.d.AdjustHijriDays)
                  .replace(/swn=\w+/"swn=" + data.d.ShowWeeks));
          });
      }
  });

After the change is made, access the datepicker and language appears correctly with the Date Format included as shown in image below.

If we access the html associated in the datepicker control, we are able to see the Lcid is different with the correct Regional Setting lcid "2070".


Convert REST/Raw Date to correct Format

After we correct the SharePoint Control DateTimeControl we should start to convert Date to string with the correct Language Format, for this the following example make the convertion of Date to String with the Language associated in the Site.

The following exame make a call to Object Web/Created to return the Date when the Site was created and include in a Text Box with the Date format associated with the Culture.

$.ajax({
        url: getQueryStringParameter("SPAppWebUrl") + "/_api/Web/created",
        method: "GET",
        headers: { "Accept""application/json; odata=verbose" },
        success: function (data) {
            $('#OutputDate').val(new Date(data.d.Created).format(Sys.CultureInfo.CurrentCulture.dateTimeFormat.ShortDatePattern));
        } 
    }); 

for this example the raw output date will be "2014-11-21T09:57:17" and the method "Date(data.d.Created).format(Sys.CultureInfo.CurrentCulture.dateTimeFormat.ShortDatePattern)" converts the Date to the Culture Date Format that is associated in the Server but by default is "1033" as shown bellow image.



To make the correct Date format convertion you need to include the following reference in your App Page, JS reference to SP.DateTimeUtil.js.

This SharePoint Object make the convertion to the correct Lcid for this case "PT-pt"

<SharePoint:ScriptLink Name="SP.DateTimeUtil.js" runat="server" LoadAfterUI="true"   />



Deploy the new version of the App and validate the Date format from the REST call and will be with the correct Date Format in this case for "PT-pt" and "2070".

After this change is made you can make the call to date and make the JS convertion from String to Date using the method "parseLocale"

var date = Date.parseLocale($('#OutputDate').val());

and returns the value as a date without having error of bad Format of Date 


With the correct Date Object you are able to make the necessary changes in your SharePoint Hosted App without incorrect formats and issues in SharePoint controls.
A big thank you to my colleague "Selim Gezgin".

Support Articles:
Using SharePoint’s DatePicker Control:

Hope you like this article,
Kind regards,
André Lage

quinta-feira, Outubro 09, 2014

How many Ribbons options can you hide in a minute? How much productive can you be!

I see a lot of article talking the SharePoint ribbon manipulation using Css and Javascript, but do you really want to use JS and CSS for this type of task?
After review a lot of this articles about CSS and JS i ask my self,  how much time/effort is enough to manage this type of customizations almost all of them take minimal 1 hour "find the Ribbon location, create CSS and JS, upload file do Library, edit web part and include reference to files, do the same task for "Add, edit, View Form", do the same for other Libraries,,,,"

After review the time here are a list of problems founded with this approach:
  • Multiple WebPart with injected javascript could turn pages slow. 
  • Custom JS code could break the MDS and afect the load page performance
  • Harder to hide/show Ribbons associated to permissions, requires code.
  • This approach could not follow company policies and could require changes in CSS
  • A lot of this Custom code don't have documentation to explain what was done and where was implemeted "Pages" turnning very hard to other developers/consultant understand changes or migrations
SharePoint already has Objects to make this type of management in a way you can be compliant with your client, follow the company policies and avoid issues described before and Migrations
The problem here there isn't user interfaces to manage this objects and Ribbons options and here the Processlynx Custom Action and Ribbon Manager could help.

If you are a developer and you want to do it by yourself here are nice documentation you about UX in SharePoint 2013 that could help you understand the effort associated and the Processlynx Ribbon Manager app is trying to avoid that.
SharePoint 2013 and SharePoint Online solution packs

If you are a developer here a article that explains the XML structure with the complexity of Ribbons.
Examples of Ribbons Customization in SharePoint 2013

The Processlynx Ribbon Manager app compiles all this options needed to support the Management of Ribbons and Customs Actions like"Ribbons Locations, Image Locations, Content types associate, lists and others options" to became more efficient and fast customizations in SharePoint Sites.

Processlynx Ribbon Manager App 
Processlynx Custom Action and Ribbon Manager
You can make a test using the free Office Store version limited to App Web
Processlynx Custom Action And Ribbon Manager Demo

This video shows how easy the app hide Ribbons using a user friendly App interface and SharePoint UserCustomAction Object in background, for this case used the "PLX Custom Action and Ribbon Manager", this example hideRibbons options from the rich text edit option from Wiki Pages.



This video show another example on how you can select a specific list and Wiki pages and hide some Ribbons locations.

Hidden Locations from Library 

  • Ribbon.Library.Actions.Sync
  • Ribbon.Library.Actions.MyLinks
Hidden Locations from Wiki Page

  • Ribbon.WikiPageTab.PubPageActions.Preview
  • Ribbon.WikiPageTab.Share.ViewAnalyticsReport
  • Ribbon.WikiPageTab.PubPageActions.SetHomePage




Support Links:
Processlynx Custom Action and Ribbon Manager
New features released for app Processlynx Custom Action and Ribbon Manager
Processlynx Custom Action And Ribbon Manager Demo
Examples of Ribbons Customization in SharePoint 2013

Hope you like this Article
Kind regards, 
André Lage

quinta-feira, Outubro 02, 2014

Export/Import SharePoint objects using JSON and REST in App

One big request from IT Managers and Office 365 SharePoint Site is about Migrations of data and SharePoint Objects from SharePoint Site, yes there is a lot of tools that help you making this type of migration,we hear a lot about moving users, Lists, Content types but how this really works...
We can have multiple ways since SharePoint Object Model Server Side, Client Side Object Model or REST operations as examples.
This example show how you can use the data in JSON base from REST operations and SharePoint Objects from SharePoint Sites then change it and import to different SharePoint sites .

The created SharePoint App model shows how we can export and import SharePoint Objects using JSON and REST with Javascript.

This type of method can be very useful to move SharePoint Site Configurations to multiple sites, for this example used the "RoleDefinition" object to export a existing RoleDefinition Object and import with a different name using JSON data.



Support documents:
"Users, groups, and roles REST API reference"
http://msdn.microsoft.com/en-us/library/office/dn531432(v=office.15).aspx
"How to Convert REST Call to SharePoint JSOM Object (ECMAScript)"
http://aaclage.blogspot.ch/2014/04/how-to-convert-rest-call-to-sharepoint.html


How the App Works?

The app get a existing RoleDefinition permission Name in the SharePoint site and make a REST operation to return the JSON data associated.
The first thing was get the Name of a permission in Permission Levels, you can access the page following the Top Right Menu "Site settings > Site Permissions > Ribbon "Permissions Levels"".





Export JSON Roledefinition

When the Permission name is selected access to ExportImport App and select the Option "Export RoleDefinition JSON" and the JSON data is displayed in the TextArea.



Code:
function ExportJson() {
    var executor = new SP.RequestExecutor(SPAppWebUrl);
 
    executor.executeAsync({
        url: SPAppWebUrl + "/_api/SP.AppContextSite(@target)/Web/Roledefinitions?$filter=Name eq '" + $('#Roledefinition').val() + "'&@target='" + SPHostUrl + "'",
        method: "GET",
        headers: { "Accept""application/json; odata=verbose" },
        success: function (data) { $('#ExportJSON ').val(data.body); SP.UI.Notify.addNotification('Roledefinitions exported with Success!!'false); },
        error: function (sender, args) {
            SP.UI.Notify.addNotification('Request failed. ' + sender.statusText + '\n' + sender.statusCode);
        }
    });
}

Import JSON Roledefinition

Copy the JSON data and paste in the Import JSON TextArea and provide a new Name for the RoleDefinition and select "Import new Roledefinition JSON".
This operation will send a POST Method by REST with the JSON data and properties associated in the Body of the message to SharePoint.
After this the object should be created with success.


Code:

function ImportJson() {
    var item = JSON.parse($('#ImportJSON').val()).d;
    var executor = new SP.RequestExecutor(SPAppWebUrl);
    if (item.results.length == 1) {
        executor.executeAsync({
            url: SPAppWebUrl + "/_api/SP.AppContextSite(@target)/web/roleDefinitions?@target='" + SPHostUrl + "'",
            method: "POST",
            body: "{ '__metadata': { 'type': 'SP.RoleDefinition' }, 'BasePermissions':{ '__metadata': { 'type': 'SP.BasePermissions' }, 'High': '" + item.results[0].BasePermissions.High + "','Low':'" + item.results[0].BasePermissions.Low + "'}, 'Description': '" + item.results[0].Description + "', 'Name': '" + $('#NameRoledefinition').val() + "', 'Order': " + item.results[0].Order + " }'",
            headers: {
                "content-type""application/json; odata=verbose"
            },
            success: function (data) { SP.UI.Notify.addNotification('New role "' + $('#NameRoledefinition').val() + '" Roledefinitions imported with Success!!'); },
            error: function (sender, args) {
                SP.UI.Notify.addNotification('Request failed. ' + sender.statusText + '\n' + sender.statusCode);
            }
        });
    } else {
        SP.UI.Notify.addNotification('More than 1 item'false);
    }
   
}

After the success Message from the last operation, you can refresh the Permission Level Page and validate if the new RoleDefinition was created with sucess.





For the ExportImport App Project you can access the following link: http://1drv.ms/1xDqjhT

Hope you like this Article, 
Kind regards, 
André Lage