Wednesday, 20 March 2013

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









Related Articles