Wednesday, 20 March 2013

SharePoint 2013 App Google Drive Import Walk-through Part III


More innovated Version
The beta version was meant to test the potential of the SharePoint hosted apps, which is great potential but because of the first version require the user to setup his own Google Drive API using API Console, I decided to move to the Provider Hosted application.

Deploying the same solution as a windows azure website will remove the headache required to set up the app for single deployment.
Adding the ribbon button & Utilize the provider hosted application
The new version of the application also enables the user to import Google drive files to any document library by adding new ribbon button called “Google Drive Import” under the files ribbon group.

when the user clicks the import from Google Drive button a SharePoint dialog will open and Import.aspx page will be opened with the appropriate parameters needed like 


Steps
   1.Follow the same steps to create the initial version of the application mentioned in my previous blog post , just select the Provider hosted type instead of the SharePoint hosted app



2.After selecting the provider hosted option two different projects will be added to your solution , one of them is the SharePoint app project and the other is Web Application

3.Utilizing the same code in the first version in Import.aspx
    
    4.Adding Server Side Static method to do the import using the SharePoint client context



Simply this Static method will be called from JavaScript action on the Import.aspx page once the user clicks import




The AddFileToLibrary function is an asynchronous function you need to add call back functions as well



When the User clicks the close button the dialog will be closed and the parent page will be refreshed to display the newly added document a single line of JavaScript code is used to facilitate this behavior 


 5.     To create the ribbon button simply right click the SharePoint app project and click add new item Select the ribbon custom action and name it “GoogleDriveImportRibbon”

The elements.xml file of the custom action will be as below, note that I add listId to the standard token to be able to upload the selected files to the appropriate document library



Also you need to specify the ribbon button image which points somewhere in the ~remoteAppUrl which represents the remote Windows Azure website URL


6.In order to publish your app you need to create Client ID go to http://sellerdashboard.microsoft.com

after successful login click on client ids and select add new oauth client id 

Clicking add new oauth client id opens  the form below




 Just add friendly name and app domain and redirect URL then press generate, for the googledriveImport the Client ID is as below


In order to publish your application you need to keep
·        Client id
·        Client secret 
7.Create publishing profile for the Google Drive Import website , the easiest way to publish the site is to use Windows azure website
a.      Register for a free 3 month trail azure evaluation plan.
b.     Create your new website and select your domain name in my case it was
googledriveimport.azurewebsites.net




c.      After creating the website on windows azure platform , download the publishing profile.



d.      Use the downloaded publishing profile to publish your application by importing the profile as below 


e.      Right click the SharePoint 2013 application project and select publish  select the publishing profile you just imported 



f.      Enter the website URL and the client ID and client secret from the seller dashboard step.


follow the wizard and set back for couple of minutes your azure website and SharePoint application will be published 

Test your application by uploading it to your developer site then publish it to the app store 




























SharePoint 2013 App Google Drive Import Walk-through Part II

This blog entry is second part in series of blog post to walk-through the creation of Google drive import  application


What you’ve already got so far
You will find that some logic been already added but it’s very simple to just display the logged in user name using the JavaScript client object model
var context;
var web;
var user;

// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model

$(document).ready(function () {
    context = SP.ClientContext.get_current();
    web = context.get_web();
    getUserName();
});
// This function prepares,loads, and then executes a SharePoint query to get the current users information
function getUserName() {
    user = web.get_currentUser();
    context.load(user);
    context.executeQueryAsync(onGetUserNameSuccess, onGetUserNameFail);
}
// This function is execute if the above OM call is successful
// It replaces the contents of the 'helloString' element with the user name
function onGetUserNameSuccess() {
    $('#message').text('Hello ' + user.get_title());
}
// This function is executed
if the above call fails
function onGetUserNameFail(sender, args) {
    alert('Failed to get user name. Error:' + args.get_message());
}
What to Add

now let's try the specific items related to the application itself , let's start with the needed style sheets and javascript files used in this early version of the application
  • Style and JavaScript references

Because I’m using the JQuery datatables plugin I needed to add references to the DataTables scripts also adding metro style JQueryUI
  • CSS added to the Content Folder like below


  • Reference Scripts added to the script Folder



  • Application Pages
the application consists of two different aspx pages the first one is the setting page in which the user set his google drive api key and client ID
    • Settings page :Settings.aspx
<h1>App Settings</h1>
    <br />
    <br />
    <table>
        <tr>
            <td><span>Google Drive API Key:</span> </td>
            <td><textarea  id="txtAPI_KEY"  cols="50"></textarea></td>
        </tr>
        <tr>
            <td><span>Google Drive Client ID:</span> </td>            
            <td><textarea  id="txtCLIENT_ID" cols="50"></textarea></td>
        </tr>
        <tr>
           
            <td colspan="2" align="center"> 
                <div>
                    <a href="#" onclick="saveSettings();" id="btnSave">Save</a>
                    <a href="default.aspx" id="btnCancel">Cancel</a>
                </div>
            </td>
        </tr>
     </table>



 The setting page is used to set the Google Drive API application key and Client ID, it simply store the value within the website properties , and by website I mean the SharePoint application itself as it will be deployed as an isolated website.


   

The settings.aspx webpage calls saveSettings() function which stored the data within the website properties.

Settings.js
The Javascript file contains the code utilized in the Settings.aspx webpage

$(document).ready(function () {
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', readApplicationSettings); 
});
function readApplicationSettings()
{
       var context = new SP.ClientContext.get_current();
    var web = context.get_web();
       this.props =  web.get_allProperties();  
       context.load(this.props);
    context.executeQueryAsync(Function.createDelegate(this, gotProperty), Function.createDelegate(this, failedGettingProperty));
}

function gotProperty() {
      
       $("#txtCLIENT_ID").val(this.props.get_item("CLIENT_ID"));
       $("#txtAPI_KEY").val(this.props.get_item("API_KEY"));
      
}
function failedGettingProperty() {
    alert("Can't get the web properties");
}
function saveSettings()
{
       var context = new SP.ClientContext.get_current();
    var web = context.get_web();
       this.props=web.get_allProperties();     
       this.props.set_item("API_KEY", $("#txtAPI_KEY").val());
       this.props.set_item("CLIENT_ID", $("#txtCLIENT_ID").val());
       web.update();
       context.executeQueryAsync(Function.createDelegate(this, onSettingsSaveSuccess), Function.createDelegate(this, onSettingsSaveFailure));
      
}
      
function onSettingsSaveSuccess()
{
       alert("Application Setting Saved");
       window.location="default.aspx";
}

function onSettingsSaveFailure()
{
       alert("Error Saving the settings..!");
}

$(function () {
    $("#btnSave").button();
    $("#btnCancel").button();
});

Deault.aspx

This is the application main page which contains the datatable displays your Google drive and each item has dropdown list for each file to select the export format from Google drive to SharePoint Library.
  <div>
        <p id="message">
            <!-- The following content will be replaced with the user name when you run the app - see App.js -->
            initializing...
        </p>
        <div style="float:right;">
                     <a href="settings.aspx" id="btnSettings">Change Settings</a>
                <a href="../Lists/MyDocuments" id="btnViewDocs">View Documents</a>           
        </div>
    </div>
    <br />
       <div id="container">
        <div>             
             <table cellpadding="0" cellspacing="0" border="0" class="display" id="DocsDataTable">
                   <thead id="thead" style="display:none;">
                          <tr>
                                 <th width="20%">Title</th>
                                 <th width="13%">Create Date</th>
                                 <th width="13%">Modified Date</th>
                                 <th width="13%">Modified By Me Date</th>
                                 <th width="13%">Viewed By Me Date</th>
                        <th width="13%">Last Modified User</th>
                        <th width="10%">View</th>
                        <th width="5%">Select Export Format</th>
                          </tr>
                   </thead>
                   <tbody> 
                                  <tr>
                                         <td colspan="8" id="tdMessage"></td>
                                  </tr> 
                   </tbody>
            </table>
        </div>
        <div class="spacer"></div>
    </div>
    <br />
    <div id="divImport" style="display:none;"> 
        <div>
            <input type="checkbox" id="chkOverwrite" name="overwrite" >Overwrite Existing Files?</input>
        </div>
        <div>       
            <a id="btnImport" href="#" onclick="importSelectedRows();" >import</a>      
        </div>
    </div>  
    <div id="pop-up" style="display:none;">
        <!-- gif represents the import loading -->
        <img src="../Images/ajax-loader.gif" id="imgLoading"/>
        <!-- the below text will be updated upon each file import -->
        <p id="importText"></p>       
        <a href="#" onclick='$("#pop-up").dialog("close");' id="btnClose" style="display:none;">Close</a>          
    </div>
Apps.js

 This file contains almost all the logic the application used
·        Load the Google Drive API
gapi.client.load('drive', 'v2', handleClientLoad);
·        Definition of the Google Drive API related variables

var CLIENT_ID = '597646573398.apps.googleusercontent.com'; //Google drive API client id
var API_KEY = "AIzaSyA9Es1Ej7H8BCYPYkSjhbkNNTdrd-cmS_o"; //api key
var SCOPES = [                   
         'https://www.googleapis.com/auth/drive.readonly.metadata',
        'https://www.googleapis.com/auth/drive.readonly',
        'https://www.googleapis.com/auth/drive',
        'https://www.googleapis.com/auth/drive.file',
        'https://www.googleapis.com/auth/drive.metadata.readonly'
        // Add other scopes needed by your application.
        ];
var File_List_URL = "https://www.googleapis.com/drive/v2/files"; //url to get the google drive user files
·        Authenticate the request
function checkAuth() {
       try
       {
        //wait until the gapi is fully loaded
           if (typeof (gapi.auth) == 'undefined') {
               displayMessage('error', 'gapi is not loaded!', true);        
           } 
           else {
               gapi.auth.authorize(
            { 'client_id': CLIENT_ID, 'scope': SCOPES.join(' '), 'immediate': true },
            handleAuthResult);
           }
          
       }
       catch(e)
       {            
              displayMessage('error',e,true);
       }
}

· How to handle the authentication Result
function handleAuthResult(authResult) {
       try
       {       
           if (authResult && !authResult.error) {                   
               GetFiles();
           } else {
               // No access token could be retrieved, force the authorization flow.                   
               displayMessage('error', "can't  authenticate app for Google drive API check App Settings and Ensure you authorize the api to access your files then refersh the page", true);
               gapi.auth.authorize(

             { 'client_id': CLIENT_ID, 'scope': SCOPES, 'immediate': false },
             handleAuthResult);
              }
       }
       catch(e)
       {
              displayMessage('error',e,true);
       }
}


·        Get the Actual File List as JSON object
function GetFiles() {
       try
       {
        //beging loading data
           $("#tdMessage").html("Loading data ....");
           var accessToken = gapi.auth.getToken().access_token;
           var xhr = getXMLHttpRequest();
           xhr.open('GET',File_List_URL+'?key='+API_KEY);
           xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
           xhr.onload = function () {
               renderFiles(xhr.responseText);
           };
           xhr.onerror = function () {
               displayMessage('error','Error Listing Your Google Drive Files');
           };
           xhr.send();
       }
       catch(e){           
              displayMessage('error',e,true);
       }
}

After the files been retrieved the user can select the appropriate format to export these files from Google Drive then press the Import button

In the Third part of this series we will discuss more innovated approach









SharePoint 2013 App:Google Drive Import Walk-through Part 1


Today I will start explaining in details the SharePoint 2013 application I built  I will start with my first published application ever which is Google Drive Import Beta

The Idea

I came up with the idea when I started to use SharePoint 2013 for the very first time and new about the newly introduced app platform, I was facing too much trouble using excel files I hosted over Google Drive, so It just hits me everyone should be able to migrate his office documents from Google Drive to SharePoint platform to enjoy the amazing experience of the Office Web Apps


First Version “SharePoint Hosted"

The first version supposed to be a beta version of the application to test drive the SharePoint hosted application, it was a pure JavaScript

 Prerequisites

  • Installation of the VS2012 is recommended , you can use the web-based application builder NAPA, but it's highly recommended to download and install VS2012 
  • Installation of the Microsoft Office Developer Tool for VS2012 can be easily obtained by Microsoft Web Platform Installer.
  • If you are using Windows 7 it has to be SP1


Steps

1.     Create new project

  


2.     Select  Office/SharePoint from the side navigation and then select App for SharePoint template



3.     Name your solution and your project also set the physical  Location for the solution and project.
4.     Point to the URL of the development environment you set up either locally or as in my case your SharePoint online developer website
Also select from the dropdown list the type of the SharePoint App which in our case in this beta version I used the  SharePoint-hosted application type 



The visual studio will try to connect to the site you already provided so it will prompt you for the credentials
5.     Press finish and wait for the visual studio to create the SharePoint App project
6.     This is what you will get after Visual Studio finish creating  your project



The files been created for you are the
·        Default.aspx
·        Elements.xml
·        Script Folder
o   _references.js
o   App.js
o   Elements.xml
o   jquery-1.7.1.intellisense.js
o   jquery-1.7.1.js
o   jquery-1.7.1.min.js
·        AppManifest.xml
·        packages.config

7.     Start Customizing the App properties
Open the AppManifest.xml it will open in the designer view like below



1.     Edit the application Title
2.     Edit the application Name
3.     Set the version Numberà this is very important as it must match the application details you are going to enter while submitting this application to the Office Store.
4.     Application Icon
5.     Start Page , So far we have only single ASPX webpage which is Default.aspx
6.     Query String it’s the parameters needed to be passed to this page , this will come in handy when walking through the Provider Hosted Application Type
Note: the application page you have is only ASPX page with no code behind.
8.     Start Adding the Logic

In Part II we will continue walking through the whole application implementation