Page Life Cycle framework: execution steps - akumina/AkuminaTraining GitHub Wiki
Applies to
Akumina Foundation 3.4 and above
Overview
The Page Life Cycle is a series of steps that are executed when a user navigates to a page. This lifecycle contains default steps that execute certain actions, for example:
- Load user settings and properties
- Obtain a graph token
- Populating html markup
- Provide “Loading…” feedback to the user
This execution process can be modified by a developer by preventing steps from running and/or adding new steps to the life cycle.
Relationship of the Page Life Cycle, UserContext, and Widgets
As shown in the diagram above, the UserContext is the funnel point and a level of abstraction between the Page life cycle steps and the widgets. The steps in the page life cycle can manipulate the UserContext by adding in additional properties or changing default properties such as language. This manipulation ensures that those changes are available to all other callers of the UserContext such as the widgets.
All of the Akumina widgets are written to talk to the UserContext.
So for example this is how we do personalization, where we have a user specific property, obtained from Azure AD or the Profile service via a step in the page life cycle. This property can then be used to filter articles shown to the user, so that they see only items relevant to their department. In another example, we use the user's city to display personalized weather.
Use cases
There are several use cases where a developer would want to use this function, for example:
- Obtain the user's location - Contact an IP lookup service and put that information into the user context.
- Getting user information from a 3rd party system - such as a CRM. Obtaining a CRM user id, so that other widgets can display information based upon that value.
- Set the user's language based on their browser setting - Instead of the system default language, set the default language to the user's browser language.
Our example follows the second use case, as we will be using the browser language setting in place of the user selected one.
View Out of the Box Steps
The Out of the Box Steps within the Page Life Cycle are stored as CONSTANTS within the ConfigurationContext object. Open a developer console within your browser on a site with the Akumina Framework enabled and type the line below
Akumina.Digispace.ConfigurationContext.CONSTANTS
A JSON object will be returned. Expand it and you can investigate the status of each out of the box step. If the CONSTANT is true, the step is enabled. Else the step is disabled.
Removing a step
Out of the Box Page Life Cycle Steps can be controlled via entries in the DigispaceConfigurationIDS_AK list. In this example, we will deactivate the LOADER_STEPS_ENABLE_LOADUSERLANGSETTINGS step by adding an entry to the DigispaceConfigurationIDS_AK list as shown below:
New Item
Title
LOADER_STEPS_ENABLE_LOADUSERLANGSETTINGS
Value
false
Add custom steps
To add a custom steps, we create an object in the AdditionalSteps namespace.
You can call "MoreSteps" anything you would like, as long as it is apart of the "AdditionalSteps" object
You can also create multiples, ie AdditionalSteps.MyAdvancedSteps, AdditionalSteps.SomethingElse, it will always run AdditionalSteps.XXYY.Init()
In our example we declare a single step that will run the Init function of the object DevTrainingSteps.LoadUserLanguageFromBrowser.
if ((typeof AdditionalSteps.MoreSteps) === 'undefined') {
AdditionalSteps.MoreSteps = {
Init: function () {
var steps = [];
steps.push({
stepName: "Parallels",
additionalSteps: [
{
name: "Get Language Setting From Profile",
callback: DevTrainingSteps.LoadUserLanguageFromSPProfile.Init
}
]
});
return steps;
}
}
}
DevTrainingSteps.LoadUserLanguageFromBrowser Is the object that we use as our callback, and the Init method is the entry point.
We first obtain the user's browser language via navigator.language. Next, we look that language up in the list of active languages. If it is not there, we default to en-us. If the user's language is present, we then set the system to use that language.
var DevTrainingSteps = DevTrainingSteps || {};
if ((typeof DevTrainingSteps.LoadUserLanguageFromBrowser) === 'undefined') {
DevTrainingSteps.LoadUserLanguageFromBrowser = {
Init: function () {
// obtain the language from the user browser
var profileLanguage = navigator.language;
// generate ll-cc language
var llccLanguage = profileLanguage;
if (llccLanguage.indexOf("-") == -1){
llccLanguage = profileLanguage + "-" + profileLanguage;
}
Akumina.AddIn.Logger.WriteInfoLog('!!!!!!!!!!!!!!!!!!!!!');
Akumina.AddIn.Logger.WriteInfoLog(profileLanguage);
var language = profileLanguage.split(",")[0];
var languageManager = new Akumina.Digispace.Data.LanguageManager();
languageManager.GetLanguages().then(function (activeLanguages) {
var foundActiveLanguage = false;
for (var i = 0; i < activeLanguages.length; i++) {
if (activeLanguages[i].languageCode.toLowerCase() == language.toLowerCase() ||
activeLanguages[i].languageCode.toLowerCase() == llccLanguage.toLowerCase()) {
language = activeLanguages[i];
foundActiveLanguage = true;
break;
}
}
if (!foundActiveLanguage) {
Akumina.AddIn.Logger.WriteInfoLog('Language not found - default to 1033 - user language was=>' + language);
language = {
title: 'English (U.S.)',
languageId: 1033,
languageCode: 'en-US',
direction: 'ltr',
isDefault: true,
isActive: true,
isSiteVisible: true,
fallbackLanguageId: null
};
}
DevTrainingSteps.LoadUserLanguageFromBrowser.LoadUserLanguageFile(language);
},
function (errormsg) {
Akumina.AddIn.Logger.WriteErrorLog('Error Loading Active Languages');
def.resolve();
});
},
// This loads the language file for the given language
LoadUserLanguageFile: function (language) {
var userlang = {
languageCode: language.languageCode,
languageId: language.languageId,
fallbackLanguageId: language.fallbackLanguageId
};
Akumina.Digispace.UserContext.SetLanguage(userlang);
var url = _spPageContextInfo.siteAbsoluteUrl + '/Style Library/DigitalWorkplace/Content/Language/' + language.languageCode + '.js';
DevTrainingSteps.LoadUserLanguageFromBrowser.LoadScript(url).then(function () {
Akumina.Digispace.AppPart.Eventing.Publish('/loader/onexecuted/');
},
function () {
Akumina.AddIn.Logger.WriteErrorLog('Error Loading Language Script - ' + url);
});
},
// This loads the language file via ajax
LoadScript: function (url) {
var def = $.Deferred();
jQuery.ajax({
url: url,
dataType: 'script',
async: true,
success: function () {
Akumina.AddIn.Logger.WriteInfoLog('Loaded Language File - ' + url);
def.resolve();
},
error: function (jQxhr, errorCode, errorThrown) {
alert('Error Loading Language File - ' + url);
Akumina.AddIn.Logger.WriteErrorLog('Error Loading Language File - ' + url);
def.resolve();
}
});
return def;
}
}
};
References
To learn how to customize the Page Life Cycle using the Akumina Framework see the following articles: