/*
==APPLICATION MAINTENANCE WINDOW LIBRARY JAVASCRIPT==
Enables target portal to utilize application maintenance specified on cdph-maintenance environment.
Maintenance for the whole website as well as any subsite/subdirectories within the website.
Ver 1.0.0 - Base version
Changelog:
>>2024/08/09 - Base version 1.0.0 established.
>>2024/10/02 - Modified to use mwv-3 path and pass the full path.
-Normally would increment the iteration, however, this is meant to be an upgrade-in-place for immediate use.
-This will technically still be notated as 1.0.0.
*/
//----------Reserved global variables--------------
var APPMW_maintenanceURL = "https://cdph-maintenance.cdph.ca.gov";
var APPMW_maintenanceURL_mwPath = "/mwv-3/";
var APPMW_currentUser; //Set outside after including the script but before calling any function. Need liquid to set email.
var APPMW_MessageObject;
/*APPMW_MessageObject current structure:
data: {
type: "AppMaintenance"
status: either "DisplayPaymentMaintenance" or "StartPaymentMaintenance". States the maintenance evaluation.
content: returns the HTML/message content stated in the maintenance manager window
exemptionArray: array of emails of users that should be exempt from the payment maintenance behavior
startDate: Start Date and Time of maintenance window
endDate: End Date and Time of maintenance window
}
*/
var APPMW_MessageObject_Subsite;
/*APPMW_MessageObject current structure:
data: {
type: "AppMaintenanceSubsite"
status: either "DisplayMaintenance" or "StartMaintenance". States the maintenance evaluation.
content: returns the HTML/message content stated in the maintenance manager window
exemptionArray: array of emails of users that should be exempt from the payment maintenance behavior
startDate: Start Date and Time of maintenance window
endDate: End Date and Time of maintenance window
subsite: the current subsite
}
*/
//------------------FUNCTIONS----------------------
/*
============================
Function APPMW_InitializeAppMaintenance
-Prerequisite: None
-Use: Should be called first, ideally in the header.
Initializes the global object "APPMW_MessageObject" which returns the response
from the maintenance site on whether maintenance is active or not. The other functions make use of this object.
However, it's possible to only run this function, and the developer is able to manipulate the object
such as customizing the message/content. This is asynchronous so to use it, should use then() and wrap
following synchronous actions inside.
-Technical details: Appends an iframe to the body to load up the maintenance site and receives a message.
The message is then stored in the global variable "APPMW_MessageObject" for further use.
-Usage: No parameters. Use as a promise and use then() to call the other functions.
============================
*/
async function APPMW_InitializeAppMaintenance(){
//Prepping event listener to listen for iframe loading the maintenance site.
//If successful, APPMW_MessageObject will contain the maintenance info for this site.
window.addEventListener("message", function(message) {
if(message.origin == APPMW_maintenanceURL && message.data.type == "AppMaintenance") {
APPMW_MessageObject = message; //Data contains status and content.
}
});
var targetIframeID = "APPMW_iframe";
if(!document.getElementById(targetIframeID)){
var cdphmwNode = document.createElement("span");
cdphmwNode.innerHTML=`
`;
document.body.appendChild(cdphmwNode);
}
var targetIframe = document.getElementById(targetIframeID);
//Changing the iframe source to query the maintenance site for maintenance info regarding this site.
const wait_iframe_Reload = () => (
new Promise(resolve =>
targetIframe.addEventListener('load', () => resolve())
));
targetIframe.src = ""+APPMW_maintenanceURL+APPMW_maintenanceURL_mwPath+"?System=" + document.location.hostname.split(".")[0];
await wait_iframe_Reload();
return wait_iframe_Reload;
};
/*
============================
Function APPMW_InitializeSubsiteAppMaintenance_OnlyFirst
-Prerequisite: None
-Use: Uses the original version of evaluating subsite and will pass only the first two subdirectories.
It has been evaluated that we'll try the entire path and look for the pattern of "/{app}-".
Only use this if necessary. Otherwise, use "APPMW_InitializeSubsiteAppMaintenance"
Should be called first, ideally in the header.
Initializes the global object "APPMW_MessageObject_Subsite" which returns the response
from the maintenance site on whether maintenance is active or not. The other functions make use of this object.
However, it's possible to only run this function, and the developer is able to manipulate the object
such as customizing the message/content.
-Technical details: Appends an iframe to the body to load up the maintenance site and receives a message.
The message is then stored in the global variable "APPMW_MessageObject_Subsite" for further use.
-Usage: Use as a promise and use then() to call the other functions.
Parameter overrideSubsite = in the event the site does not follow the pattern of domain/subsite,
can pass the desired subsite.
============================
*/
async function APPMW_InitializeSubsiteAppMaintenance_OnlyFirst(overrideSubsite){
//Prepping event listener to listen for iframe loading the maintenance site.
//If successful, APPMW_MessageObject will contain the maintenance info for this site.
window.addEventListener("message", function(message) {
if(message.origin == APPMW_maintenanceURL && message.data.type == "AppMaintenanceSubsite") {
APPMW_MessageObject_Subsite = message; //Data contains status and content.
}
});
//It's possible the APPMW_iframe exists from previous initialization. Add if not existing.
var targetIframeID = "APPMW_subsite_iframe";
if(!document.getElementById(targetIframeID)){
var cdphmwNode = document.createElement("span");
cdphmwNode.innerHTML=`
`;
document.body.appendChild(cdphmwNode);
}
var targetIframe = document.getElementById(targetIframeID);
//Changing the iframe source to query the maintenance site for maintenance info regarding this site.
const wait_iframe_Reload = () => (
new Promise(resolve =>
targetIframe.addEventListener('load', () => resolve())
));
//Changing the iframe source to query the maintenance site for maintenance info regarding this site.
var baseURL = ""+APPMW_maintenanceURL+APPMW_maintenanceURL_mwPath+"?System=" + document.location.hostname.split(".")[0];
//If the override has been specified use that. Otherwise, attempt to retrieve subsite from subdirectories.
if (overrideSubsite && typeof overrideSubsite == "string"){
targetIframe.src = baseURL + "/" + overrideSubsite + "&overrideUsed=true";
await wait_iframe_Reload();
}
else {
var pathsplit = document.location.pathname.split("/"); //Array 0 will always be empty.
//Try to find the app in the first subdirectory.
if(pathsplit[1] && pathsplit[1]!=""){
targetIframe.src = baseURL + "/" + pathsplit[1];
await wait_iframe_Reload();
};
//Sometimes the first "subdirectory" is language. Then it won't be the app. Attempt again at the next level.
//If there's no reponse here, then it's possible the first one was successful. The object remains unchanged.
if(pathsplit[2] && pathsplit[2]!=""){
targetIframe.src = baseURL + "/" + pathsplit[2];
await wait_iframe_Reload();
};
//Further leveling not implemented at the moment. Maybe can add a level specification.
//Instead, an override has been provided as a parameter if the developer wants to specify the subsite.
}
return wait_iframe_Reload;
};
/*
============================
Function APPMW_InitializeSubsiteAppMaintenance
-Prerequisite: None
-Use: Improvement from original. Will evaluate the subsite with the pattern of "/{app}-" (without quotes or braces).
This will try the entire path until a result is found for the particular app and will save it in the response.
If no results are found, the response will be empty.
Should be called first, ideally in the header.
Initializes the global object "APPMW_MessageObject_Subsite" which returns the response
from the maintenance site on whether maintenance is active or not. The other functions make use of this object.
However, it's possible to only run this function, and the developer is able to manipulate the object
such as customizing the message/content.
-Technical details: Appends an iframe to the body to load up the maintenance site and receives a message.
The message is then stored in the global variable "APPMW_MessageObject_Subsite" for further use.
-Usage: Use as a promise and use then() to call the other functions.
Parameter overrideSubsite = in the event the site does not follow the pattern of domain/subsite,
can pass the desired subsite.
============================
*/
async function APPMW_InitializeSubsiteAppMaintenance(overrideSubsite){
//Prepping event listener to listen for iframe loading the maintenance site.
//If successful, APPMW_MessageObject will contain the maintenance info for this site.
window.addEventListener("message", function(message) {
if(message.origin == APPMW_maintenanceURL && message.data.type == "AppMaintenanceSubsite") {
APPMW_MessageObject_Subsite = message; //Data contains status and content.
}
});
//It's possible the APPMW_iframe exists from previous initialization. Add if not existing.
var targetIframeID = "APPMW_subsite_iframe";
if(!document.getElementById(targetIframeID)){
var cdphmwNode = document.createElement("span");
cdphmwNode.innerHTML=`
`;
document.body.appendChild(cdphmwNode);
}
var targetIframe = document.getElementById(targetIframeID);
//Changing the iframe source to query the maintenance site for maintenance info regarding this site.
const wait_iframe_Reload = () => (
new Promise(resolve =>
targetIframe.addEventListener('load', () => resolve())
));
//Changing the iframe source to query the maintenance site for maintenance info regarding this site.
var baseURL = ""+APPMW_maintenanceURL+APPMW_maintenanceURL_mwPath+"?System=" + document.location.hostname.split(".")[0];
//If the override has been specified use that. Otherwise, attempt to retrieve subsite from subdirectories.
if (overrideSubsite && typeof overrideSubsite == "string"){
targetIframe.src = baseURL + "/" + overrideSubsite + "&overrideUsed=true";
await wait_iframe_Reload();
}
else if (location.pathname.length>1) {
//Pass the entire path.
pathname = location.pathname;
targetIframe.src = baseURL + pathname;
await wait_iframe_Reload();
}
return wait_iframe_Reload;
};
/*
============================
Function APPMW_DefaultBehavior
-Prerequisite: --APPMW_InitializePaymentMaintenance must have been executed before this.
--APPMW_currentUser should be set in the header or before calling this function.
--Element with ID of "APPMW_banner_ongoing" must exist.
--Element with ID of "APPMW_section_ongoing" must exist.
-Use: Will run the default set behavior for payment maintenance specified.
It will look for the reserved named IDs of "APPMW_banner_ongoing", and "APPMW_section_ongoing".
Default behavior results in a banner in the header stating the duration, and the specified section
will be completely replaced.
-Technical details: Calls for the default behavior functions but does not allow the IDs of the target
elements to be specified. It is assumed the target elements have already been set-up.
-Usage: No parameters.
============================
*/
function APPMW_DefaultBehavior(){
var defaultBannerMainSiteID = "APPMW_banner_mainsite";
var defaultBannerSubSiteID = "APPMW_banner_subsite";
APPMW_DefaultMainBehavior(defaultBannerMainSiteID);
APPMW_DefaultSubsiteBehavior(defaultBannerSubSiteID);
};
function APPMW_DefaultMainBehavior(mainBannerID){
APPMW_DefaultMainBehavior_Warning(mainBannerID);
APPMW_DefaultMainBehavior_Ongoing();
};
function APPMW_DefaultMainBehavior_Warning(mainBannerID){
var message = APPMW_MessageObject;
var bannerID = mainBannerID;
if (message){
if(message.data.status == "DisplayMaintenance"){
var banner = document.getElementById(bannerID);
if (banner){
banner.innerHTML = message.data.content;
banner.style.display="block";
}
}
}
};
function APPMW_DefaultMainBehavior_Ongoing(){
var message = APPMW_MessageObject;
var currentUserEmail = (APPMW_currentUser ? APPMW_currentUser.toLowerCase() : APPMW_currentUser);
if (message){
if(message.data.status == "StartMaintenance"){
if (currentUserEmail !=""&& message.data.exemptionArray.findIndex(function(i){return i==currentUserEmail;})!=-1){
console.log(currentUserEmail+" is exempt from app maintenance.");
}
else{
window.location= APPMW_maintenanceURL
+APPMW_maintenanceURL_mwPath
+"?Location="
+document.location.hostname
;
}
}
}
};
function APPMW_DefaultSubsiteBehavior(subBannerID){
APPMW_DefaultSubsiteBehavior_Warning(subBannerID);
APPMW_DefaultSubsiteBehavior_Ongoing();
};
function APPMW_DefaultSubsiteBehavior_Warning(subBannerID){
var message = APPMW_MessageObject_Subsite;
var bannerID = subBannerID;
if (message){
if(message.data.status == "DisplayMaintenance"){
var banner = document.getElementById(bannerID);
if (banner){
banner.innerHTML = message.data.content;
banner.style.display="block";
}
}
}
};
function APPMW_DefaultSubsiteBehavior_Ongoing(){
var message = APPMW_MessageObject_Subsite;
var currentUserEmail = (APPMW_currentUser ? APPMW_currentUser.toLowerCase() : APPMW_currentUser);
if (message){
if(message.data.status == "StartMaintenance"){
if (currentUserEmail !=""&& message.data.exemptionArray.findIndex(function(i){return i==currentUserEmail;})!=-1){
console.log(currentUserEmail+" is exempt from app maintenance.");
}
else {
window.location= APPMW_maintenanceURL
+ APPMW_maintenanceURL_mwPath
+ "?Location="
+ document.location.hostname
+ "/" + message.data.subsite
+ (message.data.overrideUsed == "true" ? "&overrideUsed=true" : "")
;
}
}
}
};
/*
TODO1: Need to research example use of exemptionToken where
user can specify a token in the address bar to at least be exempt
from any maintenance behavior for at least one page.
This should ideally be used for the login page.
*/