src/mobile.startup/promoCampaign/promoCampaign.js
/**
* Creates a campaign that makes showing promo drawers, modals, etc that should
* only be shown once (using localStorage) per action (when page loads, when
* user clicks on a link, etc) easier. The campaign executes a given callback
* (e.g. showing a drawer or modal) for a specific action only when it is
* eligible. A campaign can have multiple arbitrary actions via the supplied
* `actions` object. An action is either 'eligible' or 'ineligible' at any given
* time. If `ineligible`, the `showIfEligible` will not execute the `onShow`
* callback.
*
* @ignore
* @param {Function} onShow A callback intended to show something related to the
* campaign (drawer, modal, etc) when executed. The callback will only execute
* after the client calls `showIfEligible` and only if the passed in action is
* 'eligible'.
* @param {Object} actions Object of arbitrary actions that are intended to be
* either "eligible" or "ineligible" at any given time (onPageLoad,
* onHistoryLinkClick). The `onShow` callback will only be executed when an
* action is 'eligible'. For each action, the key and value should be the same
* (e.g. "onLoad":"onLoad") to mimic an enum. The client is responsible for
* notifying when each action becomes "ineligible" by calling the
* `makeActionIneligible` method. All actions can be marked as ineligible by
* calling the `makeAllActionsIneligible` method.
* @param {string} campaignName Name of campaign. This is only used to form part
* of the localStorage key for each action.
* @param {boolean} campaignActive Is campaign active
* @param {boolean} userEligible Is current user eligible
* @param {mw.storage} mwStorage Used to mark actions as ineligible
* into localStorage
* @return {mobile.startup/AmcOutreach~PromoCampaign}
*/
function createPromoCampaign(
onShow,
actions,
campaignName,
campaignActive,
userEligible,
mwStorage
) {
// This object maps actions to localStorage keys
const ACTIONS_TO_STORAGE_KEYS = {};
for ( const key in actions ) {
const a = actions[ key ];
ACTIONS_TO_STORAGE_KEYS[a] = `mobile-frontend-${ campaignName }-ineligible-${ a }`;
}
/**
* @return {boolean}
*/
function isCampaignActive() {
return campaignActive;
}
/**
* @param {string} action
* @throws {Error} Throws an error if action is not valid.
*/
function validateAction( action ) {
if ( !( action in actions ) ) {
throw new Error(
`Action '${ action }' not found in 'actions' object. Please add this to
the object when creating a campaign with promoCampaign.js if you believe
this is a valid action.`
);
}
}
/**
* @param {string} action Will check the eligibility of this action. This
* should be a value in the actions object.
* @throws {Error} Throws an error if action is not valid.
* @return {boolean}
*/
function isActionEligible( action ) {
validateAction( action );
return isCampaignActive() &&
userEligible &&
mwStorage.get( ACTIONS_TO_STORAGE_KEYS[action] ) === null;
}
return {
/**
* @ignore
* @param {string} action Should be one of the values in the
* actions param
* @param {...*} [args] Args to pass to the onShow callback
* @throws {Error} Throws an error if action is not valid.
* @return {module:mobile.startup/Drawer|null} Returns Drawer if drawer is eligible to be shown and
* null if not.
*/
showIfEligible( action, ...args ) {
if ( !isActionEligible( action ) ) {
// If not eligible, there is no sense in continuing.
return null;
}
return onShow( action, ...args );
},
/**
* @ignore
* @param {string} action
* @throws {Error} Throws an error if action is not valid.
* @return {boolean} Whether the save operation was successful
*/
makeActionIneligible( action ) {
validateAction( action );
// The value here actually doesn't matter. The only thing that matters is
// if this key exists in localStorage.
return mwStorage.set( ACTIONS_TO_STORAGE_KEYS[action], '~' );
},
makeAllActionsIneligible() {
let key, action;
for ( key in actions ) {
action = actions[key];
this.makeActionIneligible( action );
}
},
isCampaignActive
};
}
module.exports = createPromoCampaign;