Custom Widget: SP Sites List - akumina/AkuminaTraining GitHub Wiki

Custom Widget: SP Sites List

Table of Contents

  1. Introduction
  2. Widget Definition
  3. View Markup
  4. Deploying

SP Sites List View

Introduction

Version: Akumina Foundation 3.3.0.0+

The SP Sites List widget displays a list of SharePoint sites to an end user based upon their permissions. The SP Sites List widget does this by querying SharePoint for sites that a user has access to and displays them within an unordered list. A link is provided to each individual site, allowing the end user to navigate directly from there from the widget output. This widget uses the current user context to determine the appropriate sites to display, and allows configuration of the number of sites to display. By default, this value is set to “5”.

Widget Definition

Below is the custom JavaScript which encapsulates and renders the widget using the configured properties and views. This custom JavaScript is stored within digitalworkplace.custom.js, a file located in the “/Style Library/DigitalWorkplace/JS” folder.

// Begin SP Sites Widget
if ((typeof Akumina.AddIn.SPSites) === 'undefined') {
    Akumina.AddIn.SPSites = function () {
        var _cur = this;
        this.GetPropertyValue = function (requestIn, key, defaultValue) {
            var propertyValue = "";
            for (var prop in requestIn) {
                if (key.toLowerCase() == prop.toLowerCase()) {
                    propertyValue = requestIn[prop];
                    break;
                }
            }
            return (propertyValue == undefined || propertyValue.toString().trim() == "") ? defaultValue : propertyValue;
        };
        //sets the default properties on the widget.
        this.SetDefaultsProperties = function (requestIn) {
            var requestOut = requestIn
            requestOut.SenderId = _cur.GetPropertyValue(requestIn, "id", "");
            requestOut.DisplayTemplateUrl = _cur.GetPropertyValue(requestIn,
            "displaytemplateurl", "");
            requestOut.PageSize = _cur.GetPropertyValue(requestIn, "pagesize", "");
            return requestOut;
        };
        //"Init" is the main function called from the framework, everything else is specific to this widget
        this.Init = function (SiteRequest) {
            _cur.SiteRequest = _cur.SetDefaultsProperties(SiteRequest);
            _cur.SiteRequest.EditMode = Akumina.AddIn.Utilities.getEditMode();
            //Widget Framework
            var widgetName = "SP Sites";
            Akumina.Digispace.WidgetPropertyViews.AddViewForProperty(widgetName, "DisplayTemplateUrl", "TemplatePicker");

            _cur.Prerender();
        };
        this.Prerender = function () {
            var targetDiv = this.SiteRequest.SenderId;
            $("#" + targetDiv).html(Akumina.Digispace.ConfigurationContext.LoadingTemplateHtml);
            //subscribe to loader completed event, this is fired at the end of the DWP page lifecycle
            Akumina.Digispace.AppPart.Eventing.Subscribe('/loader/completed/', _cur.Render);
            //subscribe to refresh event, called by Widget Manager on DWP
            Akumina.Digispace.AppPart.Eventing.Subscribe('/widget/updated/', _cur.RefreshWidget);
        };
        this.Render = function () {
            var data = {}
            data.PageSize = _cur.SiteRequest.PageSize;
            data.Items = [];
            //retrieve site list
            _cur.RetrieveListItems();
        };
        this.RefreshWidget = function (newProps) {
            if (newProps["id"] == _cur.SiteRequest.SenderId) {
                _cur.SiteRequest = _cur.SetDefaultsProperties(newProps);
                _cur.Render();
            }
        };
        this.BindTemplate = function (templateUri, data, targetDiv) {
            new Akumina.Digispace.AppPart.Data().Templates.ParseTemplate(templateUri, data).done(function (html) {
                $("#" + targetDiv).html(html);
            });
        };
        //Queries SharePoint and retrieves a list of SharePoint sites based on user context and pagesize
        this.RetrieveListItems = function () {
            
            var siteurl = Akumina.Digispace.SiteContext.SiteAbsoluteUrl;
            var pagesize = _cur.SiteRequest.PageSize;
            
            $.ajax({
                    url: siteurl + "/_api/search/query?querytext=%27*%27&rowlimit="+pagesize+"&querytemplate=%27modifiedby:{User}%27&selectproperties=%27sitetitle%2cspsiteurl%2c%27&sortlist=%27lastmodifiedtime:descending%27&collapsespecification=%27spsiteurl%27",
                    method: "GET",
                    headers: { "Accept": "application/json; odata=verbose" },
                    success: function (data) {
                        //pass reponse data to Success Handler
                        _cur.onQuerySucceeded(data);
                    },
                    error: function (error) {
                        _cur.onQueryFailed(error.sender, error.args);
                    }
            });
        }
        //upon successful completion of the Ajax call, bind the result set to individual items array for display
        this.onQuerySucceeded = function (sender, args) {
            var results = sender.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results;
            var data = {};
            data.Items = [];
            data.HasItems = true;

            if(results.length > 0){

                $.each(results, function(index, item){
                    
                        var listItemInfo =
                            {
                                "Title": item.Cells.results[2].Value, //gets the sitetitle from the result set
                                "Link": item.Cells.results[3].Value   //gets the url from the result set
                            };
                            debugger;
                            data.Items.push(listItemInfo);
                    } ); 

            } else {
                Akumina.AddIn.Logger.WriteInfoLog('No Results Returned');
                data.HasItems = false;
            }
            //bind data to output
            if (!_cur.SiteRequest.EditMode) {
                _cur.BindTemplate(_cur.SiteRequest.DisplayTemplateUrl, data, _cur.SiteRequest.SenderId);
            }   
            
        }

        this.onQueryFailed = function (sender, args) {
            Akumina.AddIn.Logger.WriteErrorLog('SP Site List Request Failed\n' + args.get_message() + '\n' + args.get_stackTrace());
        }
    }
}
//end SP Sites Widget

JavaScript Functions

Function Description
Akumina.AddIn.SPSites Defines the Widget SPSites Addin and functions.
this.GetPropertyValue Retrieves the property value for a defined property.
this.SetDefaultsProperties Sets the default properties for the widget.
this.Init Called by the framework to instantiate the widget, passing in properties from the site. Binds view and widget name for this widget.
this.Prerender What is displayed while widget is rendering. We use subscriptions to call the this.Render function when loading is complete and this.RefreshWidget when the widget is updated.
this.Render Calls the method to retrieve the list of sites from SharePoint.
this.RefreshWidget Refreshes the widget display when updated.
this.BindTemplate Binds the template to the widget.
this.RetrieveListItems Performs the Ajax call to SharePoint passing in the user context and & of items to return. On Success, it will call onQuerySucceeded function passing in response data, otherwise it will call onQueryFailed passing in error information.
this.onQuerySucceeded If the previous Ajax call succeeded, this function will get called and will be passed the list of SharePoint sites.
this.onQueryFailed If the previous Ajax call failed, this function will get called and will be passed the corresponding error. We log it to the Akumina Log.

SharePoint Query

The most important part of this widget JavaScript is its ability to execute an Ajax call to SharePoint. The JSON response will include a list of SharePoint sites specific to the logged in user. The querystring parameters can be changed to tune your results. In the RetrieveListItems function, we find the following Ajax call using the following parameters below:

url: siteurl + "/_api/search/query?querytext=%27*%27&rowlimit="+pagesize+"&querytemplate=%27modifiedby:{User}%27&selectproperties=%27sitetitle%2cspsiteurl%2c%27&sortlist=%27lastmodifiedtime:descending%27&collapsespecification=%27spsiteurl%27"

Parameters

The following are parameters passed to SharePoint via the querystring:

Parameter Description
querytext string containing our search, in this case it is *
rowlimit the number of results to pass, configured by the widget property
querytemplate modifiedby: {User} - only results modified by our currently logged in user
selectproperties what properties we want to retrieve from SharePoint - defaults are sitetitle & spsiteurl
sortlist sort list by last modified
collapsespecification collapse results based upon spsiteurl

Object Model

SPSites Widget Object Model

Configurable Widget Properties

Widget Property Description
pagesize determines the number of results to show in the list
displaytemplateurl overrides display template via a url

View Markup

The view markup displays the result set in an unordered list, iterating over each item in the result set and displaying the title and a link to that SharePoint website.

{{#if HasItems}}
<div class="ia-announcements">
    <ul>
        {{#Items}}
        <li>
            <h4 class="ia-announcement-title"><a href="{{Link}}">{{Title}}</a></h4>
        </li>
        {{/Items}}
    </ul>
</div>
{{else}}
    <h2>No Items</h2>
{{/if}}

Next we will focus on deploying our custom widget to Akumina.

Deploying

Follow the steps below to create the widget definition, widget view, and then upload and utilize your new widget in the system.

Creating the Widget Definition JavaScript

  1. Download digitalworkplace.custom.js from the “/Style Library/DigitalWorkplace/JS” folder within SharePoint
  2. Paste the Widget Definition within digitalworkplace.custom.js
  3. Upload the updated digitalworkplace.custom.js to the “/Style Library/DigitalWorkplace/JS” folder within SharePoint

Creating the Widget View

  1. Create a new HTML file in your editor of choice. Copy-and-paste the Widget View HTML into the file and save as sites-list.html.
  2. Copy the sites-list.html file to /Style Library/DigitalWorkplace/Content/Templates/SPSites
  3. In the Management Apps tab of Interchange, click on the View Manager. Click “Add New”. In the left pane navigate to “/DigitalWorkplace/Content/Templates/SPSites” for the folder path. Click “Choose File”, navigate to your custom template (sites-list.html). Click “Save”.

Creating the App Manager Widget & Instance

  1. In the Management Apps tab of Interchange, click on the Widget Manager app. Then click on Add Widget. Create your widget with the values in the Widget Definition – Object Model section. Click Save & Exit
  2. In the Manage Widgets window, find SPSitesList and click its ‘View Widget Definitions’ button. Then click on ‘Add New’. Create your widget instance with the values in the Widget Manager – Widget Instance section. Click Save & Exit
  3. Copy the Widget Snippet of your Widget Instance for use later when adding to a page

Adding Widget to a Page

  1. Create a new Page in SharePoint or edit an existing Page.
  2. Paste the snippet into a Content Editor Web Part on a page within the site. Publish the page.
  3. Flush your cache by clicking on the Akumina icon in the left rail, clicking the refresh icon, then clicking “Refresh All Cache”
  4. Refresh the page. You will see your Flickr Widget
⚠️ **GitHub.com Fallback** ⚠️