Skip to content

Deployment Manager: Custom Subsite Definitions

GPell2 edited this page May 24, 2019 · 9 revisions

Applies to

Akumina Foundation 3.3.0.0 and above

Download

You can download the code the for SampleSite project here

Overview

The Deployment Manager SDK allows us to define custom site definitions to subsites as well as root sites. A subsite definition is essentially the same as a root site definition with the following differences:

  • Subsite Definitions require User Input for the Title, Url, and whether or not to Inherit Permissions
  • Subsite Definitions require a step that creates a new Subsite from user inputs
  • Subsite Definitions do not need to provision branding files
  • Subsite Definitions do not need to provision page layout files
  • Subsite Definitions do not need to provision Master Page files

The following article will go through the elements of a basic subsite definition

The C# class inheriting the SiteProvisionerSiteBase class

This file inherits the SiteProvisionerSiteBase class and assembles our step classes into a list of steps which is seen in the Deployment Manager App UI. We will cover the differences between a root site definition and the subsite definition here. A sample subsite instance, SampleSubSite.cs, is shown below.

public class SampleSubSite : SiteProvisionerSiteBase
    {
        public override string AssetDirectory => "SampleSubSite";

        public override string Javascript => "~/SiteDefinitions/SampleSubSite/ProvisionerFiles/js/samplesubsite.js";

        public override string FriendlyName => "Sample Sub-site";

        public override string ClassName => "SiteCreator.SampleSubSite";

        public override bool IsVisible => true;

        public override List<ISiteProvisionerStep> Steps
        {
            get
            {
                var _steps = new List<ISiteProvisionerStep>
                {
                    new ValidateUserSettings(),
                    new CreateSiteFromUserSettings(),
                    new SetSecurityOnSite(),
                    new ProvisionLists(),
                    new UploadFiles(),
                    new AddPages(),
                    new AddControlsToPages(),
                    new SetHomePage(),
                    new ResetMasterPageInheritance()
                };
                return _steps;
            }
        }

        public override List<SiteProvisionerSettingsField> UserSettings
        {
            get
            {
                var userSettings = new List<SiteProvisionerSettingsField>
                {
                    new SiteProvisionerSettingsField
                    {
                        Name = "SubSite",
                        Description = "SubSite",
                        DefaultValue = new List<SiteProvisionerSettingsListItem> {},
                        Type = typeof(List<>)
                    },
                    new SiteProvisionerSettingsField
                    {
                        Name = "Title",
                        Description = "The Title of the site to be created",
                        DefaultValue = "",
                        Required = true
                    },
                    new SiteProvisionerSettingsField
                    {
                        Name = "URL",
                        Description = "The URL of the site to be created",
                        DefaultValue = "",
                        Required = true
                    },
                    new SiteProvisionerSettingsField
                    {
                        Name = "InheritPermissions",
                        Description = "Inherit permissions from the parent site",
                        DefaultValue = true,
                        Type = typeof(bool)
                    }                   
                };

                return userSettings;
            }
        }

    }

Key Differences from the Root Site Definition

IsVisible => true

We always want our subsite definition to be visible.

UserSettings

We include user inputs for our Subsite Deployment.

SubSite

This allows the user to choose a previously deployed Subsite so individual steps can be rerun on it.

Title

The Title of the Subsite, this is a required text field for subsite deployment.

URL

The URL of the Subsite, this is a required text field for subsite deployment.

InheritPermissions

The Permissions of the subsite, this is a required boolean field for subsite deployment. When checked the subsite owners group will be the parent owners group. When unchecked the subsite owners group will be unique.

Steps specific to Subsite Definitions

The following steps are required for Subsite Definitions

CreateSiteFromUserSettings

Retrieves the Title and URL user inputs and creates a site. This step is included with our SiteProvisioning.SampleSite project and can be modified for additional inputs.

SetSecurityOnSite

Retrieves the InheritPermissions user input and sets the owners group on the newly created site. This is within the Akumina.SiteProvision.CoreSteps dll

SiteDefinitions Folder

image 2

The assets needed for the deployment of subsites are a subset of those needed for root sites

ContentEditor

The ContentEditor folder contains the ContentEditor.xml file, we need this for deploying our widgets. Do not edit or delete this file.

ListDefinitions

The ListDefinitions folder contains information that the Site Creator App uses to create lists on the subsite. This information is stored in an xml file called Lists.xml.

PageContent

The PageContent folder contains information that the Deployment Manager App will use to add content to the pages we create. This information is stored within an xml file called pages.xml.

Pages

The Pages folder designates the pages that are deployed to the Pages Library of our subsite. This information is stored within an xml file called Elements.xml. Our pages will need to reference layouts that are deployed on the root site.

ProvisionerFiles

Within the ProvisionerFiles folder we will store our provisioning javascript. Having a provisioning javascript file is required for the deployment view to function. The provisioning javascript for a subsite is shown below. This file can be modified to enhance the UI functionality of the deployment view

var SiteCreator = SiteCreator ? SiteCreator : {};

if ((typeof SiteCreator.SampleSubSite) === 'undefined') {
    SiteCreator.SampleSubSite = function () {
        var _cur = this;

        this.Init = function (model) {
            SiteCreator.Eventing.Subscribe('/SiteCreator/DeployButtonclick/', _cur.OnDeploymentClick);
            SiteCreator.Eventing.Subscribe('/SiteCreator/SelectActionChange/', _cur.SelectActionChange);
            SiteCreator.Eventing.Subscribe('/SiteCreator/SiteChange/', _cur.OnSiteChange);
            SiteCreator.Eventing.Subscribe('/SiteCreator/GetFeatureName/', _cur.GetFeatureName);
            _cur.className = model.className;
            _cur.siteContainerId = model.siteContainerId;

            //Get subsites in dropdown
            _cur.GetSubSites();

            _cur.BindEvents();
        };

        this.IsLanguageEnabled = function () {

            $('#ak-loading').show();
            var def = $.Deferred();

            $.ajax({
                url: '/api/Config/IsLanguageEnabled',
                type: 'GET',
                contentType: 'application/json; charset=utf-8',
                success: function (isLanguageEnabled) {
                    def.resolve(isLanguageEnabled);
                    //Bind dropdown
                    $('#ak-loading').hide();
                },
                error: function (xhr, textStatus, errorThrown) {
                    def.reject();
                    $('#ak-loading').hide();
                }
            });

            return def;
        };

        this.GetSubSites = function () {
            $('#ak-loading').show();

            $.ajax({
                url: '/api/connector/subsites',
                type: 'GET',
                contentType: 'application/json; charset=utf-8',
                success: function (data) {
                    for (var obj in data) {
                        if (obj.indexOf('/') > -1) {
                            var html = "<option value='" + data[obj] + "'>" + obj.substring(obj.lastIndexOf('/') + 1) + "</option>";
                            $('#ak-siteprovisioning-usersetting-SubSite').append(html);
                        }
                    }
                    //Bind dropdown
                    $('#ak-loading').hide();
                },
                error: function (xhr, textStatus, errorThrown) {
                    $('#ak-loading').hide();
                }
            });
        };

        this.IsUpgradeRequired = function (siteId) {
            var def = $.Deferred();

            $.ajax({
                url: '/api/connector/isupgraderequired?siteId=' + siteId,
                type: 'GET',
                contentType: 'application/json; charset=utf-8',
                success: function (result) {
                    def.resolve(result);
                },
                error: function (xhr, textStatus, errorThrown) {
                    def.reject();
                }
            });

            return def;
        };

        this.BindEvents = function () {
            $('#ak-siteprovisioning-usersetting-SubSite').change(function () {
                $('#ak-loading').show();
                //Display theme image in preview section
                var selectedSubSiteId = this.value;

                //Get properties of subsite
                $.ajax({
                    url: '/api/connector/siteproperties?siteId=' + selectedSubSiteId,
                    type: 'GET',
                    success: function (data) {
                        //Display properties for subsites
                        $("#ak-siteprovisioning-usersetting-Title").val(data.Title);
                        if (data.Url.indexOf('/') > -1) {
                            $("#ak-siteprovisioning-usersetting-URL").val(data.Url.substring(data.Url.lastIndexOf('/') + 1));
                        }
                        //$("#ak-siteprovisioning-usersetting-InheritPermissions").prop("checked", data.InheritPermissions);
                        $("#ak-siteprovisioning-usersetting-Image option[value=" + data.Image + "]").attr('selected', 'selected');

                        $('#ak-loading').hide();
                        //Check if version upgrade is required for selected subsite.
                        //_cur.IsUpgradeRequired(selectedSubSiteId).then(function (isUpgradeRequired) {
                        //    if (!isUpgradeRequired) {
                        //        $("#" + _cur.siteContainerId + " [id^=Step_][data-steptype=Upgrade]").hide();
                        //        if ($('input[type=radio][name=select-an-action][value=UpgradeSite]').is(':checked')) {
                        //            $("#upgradeSiteDiv").show();
                        //        }
                        //    }
                        //    else {
                        //        if ($("#" + _cur.siteContainerId + " [id^=Step_][data-steptype=Upgrade]").length == 0 && $('input[type=radio][name=select-an-action][value=UpgradeSite]').is(':checked')) {
                        //            $("#upgradeSiteDiv").show();
                        //        }
                        //        else {
                        //            $("#" + _cur.siteContainerId + " [id^=Step_][data-steptype=Upgrade]").show();
                        //            $("#upgradeSiteDiv").hide();
                        //        }
                        //    }
                        //    $('#ak-loading').hide();
                        //}, function () {
                        //    $('#ak-loading').hide();
                        //});
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        $('#ak-loading').hide();
                    }
                });
            });
        };

        this.OnDeploymentClick = function (model) {
            BaseDeployment(model, _cur.siteContainerId);
        };

        this.SelectActionChange = function (model) {
            if (model.siteContainerId == _cur.siteContainerId) {
                _cur.DisplayDepartmentProperties();
                $("#ak-siteprovisioning-usersetting-SubSite").parent().hide();
                $("#ak-siteprovisioning-usersetting-Title").val("");
                $("#ak-siteprovisioning-usersetting-Title").attr('disabled', false);
                $("#ak-siteprovisioning-usersetting-URL").val("");
                $("#ak-siteprovisioning-usersetting-URL").attr('disabled', false);
                $("#ak-siteprovisioning-usersetting-InheritPermissions").attr('disabled', false);
                $("#ak-siteprovisioning-usersetting-Image").attr('disabled', false);
                //Detect Add mode
                if ($('input[type=radio][name=select-an-action][value=CreateNewInstallation]').is(':checked')) {
                }//Detect Update mode
                else if ($('input[type=radio][name=select-an-action][value=UpdateConfigurationSettings]').is(':checked')) {
                }//Detect Individual Deployment Step mode
                else if ($('input[type=radio][name=select-an-action][value=ExecuteIndividualDeploymentSteps]').is(':checked')) {
                    //Display all department site properties
                    $("#ak-siteprovisioning-usersetting-SubSite").parent().show();
                    $("#ak-siteprovisioning-usersetting-Title").attr('disabled', true);
                    $("#ak-siteprovisioning-usersetting-URL").attr('disabled', true);
                    $("#ak-siteprovisioning-usersetting-InheritPermissions").attr('disabled', true);
                    $("#ak-siteprovisioning-usersetting-Image").attr('disabled', true);

                    //Trigger subsite change and load subsite properties
                    var firstValue = $("#ak-siteprovisioning-usersetting-SubSite option:first").val();
                    if (firstValue != "" && typeof firstValue != 'undefined') {
                        $("#ak-siteprovisioning-usersetting-SubSite").val($("#ak-siteprovisioning-usersetting-SubSite option:first").val());
                        $("#ak-siteprovisioning-usersetting-SubSite").trigger('change');
                    }

                    $("#" + model.siteContainerId + " [id='Step_Validate User Settings'] .ak-siteprovisioning-featuredeploy-btn").prop("disabled", true).css('opacity', '0.6');
                    $("#" + model.siteContainerId + " [id='Step_Create Site from URL user setting'] .ak-siteprovisioning-featuredeploy-btn").prop("disabled", true).css('opacity', '0.6');
                    $("#" + model.siteContainerId + " [id='Step_Enable Multilingual'] .ak-siteprovisioning-featuredeploy-btn").prop("disabled", true).css('opacity', '0.6');
                    $("#" + model.siteContainerId + " [id='Step_Update Friendly Urls'] .ak-siteprovisioning-featuredeploy-btn").prop("disabled", true).css('opacity', '0.6');
                    $("#" + model.siteContainerId + " [id='Step_Update List Items - Multilang Provisioning'] .ak-siteprovisioning-featuredeploy-btn").prop("disabled", true).css('opacity', '0.6');
                }
                else if ($('input[type=radio][name=select-an-action][value=UpgradeSite]').is(':checked')) {
                    $('#' + model.siteContainerId + " .ak-siteprovisioning-upgrade-btn").hide();
                }
            }
        };

        this.ShowHideMultilingualStep = function () {
            if (_cur.isLanguageEnabled) {
                $("#" + _cur.siteContainerId + " [id='Step_Enable Multilingual']").show();
            }
            else {
                $("#" + _cur.siteContainerId + " [id='Step_Enable Multilingual']").hide();
            }
        };

        this.DisplayDepartmentProperties = function () {
            $("#ak-siteprovisioning-usersetting-Title").parent().show();
            $("#ak-siteprovisioning-usersetting-URL").parent().show();
            $("#ak-siteprovisioning-usersetting-InheritPermissions").parent().show();
            $("#ak-siteprovisioning-usersetting-Image").parent().show();
        };

        this.OnSiteChange = function (model) {
            if (model.siteContainerId == _cur.siteContainerId) {
                    $("#selectActionDiv").show();
                    $("#updateConfigOption").hide();
                    $("#upgradeSiteOption").hide();
            }
        };

        this.GetFeatureName = function (model) {
            BaseGetFeatureName(model, _cur.siteContainerId);
        };
    }
};

UploadFiles

The UploadFiles folder contains all files that we want uploaded to SharePoint file libraries within our site via the UploadFiles.cs step. See UploadFiles for more details.

Download

You can download the code the for SampleSite project here

References

To learn how to leverage the Deployment Manager SDK see the following articles:

Clone this wiki locally