Name
sn_ads_setup.SNHelpSetupService
Description
Guided setup specfic service to interact with Guidance services
Script
var SNHelpSetupService = Class.create();
SNHelpSetupService.prototype = {
initialize: function() {
var helpService = new global.SNHelpService();
this.constants = new sn_ads_setup.SNHelpSetupConstantProvider();
this.helpContent = helpService.helpContent;
this.helpUtil = helpService.helpUtil;
this.helpGuidance = helpService.helpGuidance;
this.setupUtil = new sn_ads_setup.SNHelpSetupUtil();
this.helpGuidanceInteraction = helpService.helpGuidanceInteraction;
this.status = this.constants.status;
},
//Moved this method from Guidance_step_cotroller to here to accommodate task_type.
getSetupSteps: function(step_id, task_type) {
var dbController = new global.SNHelpDBController(this.constants.tables.guidance_step);
var query = "parent=" + step_id;
if(task_type == this.constants.taskType.BASIC)
query += '^task_type='+this.constants.taskType.BASIC;
if(task_type == this.constants.taskType.RECOMMENDED)
query += '^task_type='+this.constants.taskType.BASIC+'^ORtask_type='+this.constants.taskType.RECOMMENDED;
var steps = dbController.getByEncodedQuery(query, this.constants.tableColumns.order, ["sys_id", "name", "parent", "guidance", "task_type", "status", "order"]);
return Array.isArray(steps) ? steps : [];
},
// Moved this method from Guidance_controller here to fetch sys_updated_on
getGuidance: function(sys_id, fields) {
var guidanceRecord;
if (!sys_id) {
this.helpUtil.setError(this.type,this.constants.errorMessages.empty_sys_id);
return null;
}
var dbController = new global.SNHelpDBController(this.constants.tables.guidance);
guidanceRecord = dbController.getById(sys_id, fields);
if (!guidanceRecord) {
this.helpUtil.setError(this.type, this.constants.errorMessages.no_records, sys_id);
return null;
}
guidanceRecord.steps = this.getSteps(sys_id, guidanceRecord.type) || [];
return { guidance: guidanceRecord };
},
// Moved this method from Guidance_controller here to fetch sys_updated_on
getSteps: function(sys_id, type, task_type) {
var steps;
var query;
var stepFields, contentFields, content, isSetup;
var orderBy = this.constants.tableColumns.order;
if (!sys_id) {
this.helpUtil.setError(this.type,this.constants.errorMessages.empty_sys_id);
return null;
}
query = this.constants.tableColumns.guidance + "=" + sys_id;
if(task_type)
query += '^task_type='+task_type;
if(type === this.constants.setupType.GLOBAL_SETUP || type === this.constants.setupType.PERSONAL_SETUP ) {
isSetup = true;
stepFields = this.constants.restAPIKeys.setupStep;
// for setup - Only include steps with parent null (Immediate steps)
query += "^parent=NULL";
} else
return null;
var dbController = new global.SNHelpDBController(this.constants.tables.guidance_step);
steps = dbController.getByEncodedQuery(query, orderBy, stepFields);
if (!steps) {
this.helpUtil.setError(this.type, this.constants.errorMessages.no_records, sys_id);
return null;
}
for (var i= 0; i< steps.length; i++) {
content = this.helpContent.getContent(steps[i].sys_id, steps[i].layout, this.constants.restAPIKeys.setupContent) || {};
if(isSetup && Array.isArray(content) && content.length > 0) {
steps[i].content = content[0];
if(steps[i].content.related_content)
steps[i].content.related_content = this.getRelatedContent(steps[i].content.related_content);
} else {
steps[i].content = content;
}
}
return steps;
},
getRelatedContent : function(related_content) {
var dbController = new global.SNHelpDBController(this.constants.tables.content);
return dbController.getByEncodedQuery("sys_idIN" + related_content, null, this.constants.restAPIKeys.content);
},
// insert or update Category or Task Step
upsertStep: function(step_id, params) {
var result = {},
sysId,
contentResult,
config,
updateContent = false;
var dbController = new global.SNHelpDBController(this.constants.tables.guidance_step);
var content = this._hasContent(params.content) ? params.content : null;
var isPluginCategory = params.isPluginCategory;
var hasPlugiCategory = this.setupUtil.hasPluginStep(params.guidance);
delete params.content;
if(isPluginCategory && hasPlugiCategory && step_id == -1) {
result.status = 400;
result.message = gs.getMessage("Error : Category for installing plugin already exists {0}", hasPlugiCategory);
return result;
} else if(isPluginCategory) {
// Update the name of install plugin category to Plugins
params.name = "Plugins";
params.type = params.type || "group";
}
// validate the name & type params
if(step_id == -1) {
if(!params.name) {
result.status = 400;
result.message = gs.getMessage("Error: Name can't be empty");
return result;
} else if(!params.type) {
result.status = 400;
result.message = gs.getMessage("Error: Missing required param - type");
return result;
}
} else if(params.hasOwnProperty("name") && !params.name) {
result.status = 400;
result.message = gs.getMessage("Error: Name can't be empty");
return result;
}
if(GlideStringUtil.isEligibleSysID(step_id)) {
sysId = dbController.update(step_id, params);
updateContent = true;
} else {
sysId = dbController.create(params);
}
if(!sysId) {
result.status = 500;
result.message = gs.getMessage("Error creating record in table {0} ", this.table);
} else {
result.data = sysId;
result.status = updateContent ? 200 : 201;
}
if(content) {
if(content.guidance_step !== sysId)
content.guidance_step = sysId;
if(updateContent && GlideStringUtil.isEligibleSysID(content.sys_id))
contentResult = this.updateContent(content);
else
contentResult = this.createContent(content);
if(!contentResult)
gs.error("SNHelpSetupService:upsertStep - Error creating record in table {0} " + this.constants.tables.content);
}
// Create install plugin task only if its not there.
if(isPluginCategory && step_id == -1) {
this.createInstallPluginTask(params.guidance, sysId);
config = {
basic : [],
recommended : []
};
this.configurePluginsForSetupType(params.guidance, sysId, config);
}
return result;
},
/**
* Create Tasks for plugin category
* @params {categoryId} - sys_id of install_plugin category
* @returns {sys_id} of newly created install_plugin task
*
*/
createInstallPluginTask : function(guidanceId, categoryId, config) {
config = config || {};
var taskType = config.task_type || "";
var params = {
sys_id : -1,
type : "activity",
name : "Install Plugins " + taskType,
task_type : taskType ? taskType : "advanced",
parent : categoryId,
guidance : guidanceId,
rich_description: config.rich_description || "",
description: config.description || "",
status : config.status || "",
content : {
sys_id : -1,
configuration_types : "install_plugin",
table_name : "v_plugin",
title : "Install Plugins " + taskType,
records : config.records || '',
}
};
return this.upsertStep(-1, params);
},
createContent: function(params) {
var dbController = new global.SNHelpDBController(this.constants.tables.content);
params.related_content = this.upsertRelatedContent(params.related_content, false);
return dbController.create(params);
},
updateContent: function(params) {
var dbController = new global.SNHelpDBController(this.constants.tables.content);
params.related_content = this.upsertRelatedContent(params.related_content, true);
return dbController.update(params.sys_id, params);
},
upsertRelatedContent : function(relatedContent, update) {
var result;
var relatedContentSysIds = [];
if(!relatedContent || Array.isArray(relatedContent) && relatedContent.length === 0)
return null;
for(var i = 0; i < relatedContent.length; i++) {
if(update && GlideStringUtil.isEligibleSysID(relatedContent[i].sys_id))
result = this.updateContent(relatedContent[i]);
else
result = this.createContent(relatedContent[i]);
if(result)
relatedContentSysIds.push(result);
}
return relatedContentSysIds.join(",");
},
_hasContent : function(content) {
return (content && Object.keys(content).length > 0) ? true : false;
},
isValidSetupId: function(setupId) {
return GlideStringUtil.isEligibleSysID(setupId) && !!this.helpGuidance.getGuidance(setupId, ["sys_id"]);
},
/*
Gets the survy step in the given guidance
@param Guidance Id
@return [step]
*/
getSurveyStep : function(guidance_id){
var step, stepFields, orderBy = this.constants.tableColumns.order, query, dbController;
if (!guidance_id) {
this.helpUtil.setError(guidance_type, this.constants.errorMessages.empty_sys_id);
return null;
}
query = this.constants.tableColumns.guidance + "=" + guidance_id;
stepFields = ['sys_id'];
// for setup - Only include steps with parent null (Immediate steps)
query += "^parent=NULL";
query += "^type=survey";
dbController = new global.SNHelpDBController(this.constants.tables.guidance_step);
step = dbController.getByEncodedQuery(query, orderBy, stepFields);
if (!step) {
this.helpUtil.setError(this.type, this.constants.errorMessages.no_records, sys_id);
return null;
}
return step;
},
/*
Fetch interaction step status
@param interactinoId for guidance
@param taskType (basic, recommend and advacned)
@return status and timestamp
*/
getInteractionStepStatusByType: function(userInteractionId, taskType, guidanceId){
var interactions, dbController, status ='', result = {}, fields = this.constants.restAPIKeys.interactionStep, orderByField = "sys_updated_on", query = "user_interaction=" + userInteractionId+ '^step.parentISNOTEMPTY', self, step_query, stepCount=0, itrCount=0, grStep, grInteraction;
step_query = 'guidance='+guidanceId+'^parentISNOTEMPTY';
if(taskType == this.constants.taskType.BASIC){
query += '^step.task_type='+this.constants.taskType.BASIC;
step_query += '^task_type='+this.constants.taskType.BASIC;
}
if(taskType == this.constants.taskType.RECOMMENDED){
query += '^step.task_type='+this.constants.taskType.BASIC+'^ORstep.task_type='+this.constants.taskType.RECOMMENDED;
step_query += '^task_type='+this.constants.taskType.BASIC+'^ORtask_type='+this.constants.taskType.RECOMMENDED;
}
grStep = new GlideRecord(this.constants.tables.guidance_step);
grStep.addEncodedQuery(step_query);
grStep.query();
stepCount = grStep.getRowCount();
grInteraction = new GlideRecord(this.constants.tables.user_interaction_step);
grInteraction.addEncodedQuery(query);
grInteraction.query();
itrCount = grInteraction.getRowCount();
dbController = new global.SNHelpDBController(this.constants.tables.user_interaction_step);
interactions = dbController.getByEncodedQuery(query, orderByField, fields);
if(!interactions)
return null;
if(interactions && Array.isArray(interactions) && interactions.length > 0) {
self = this;
result.status = this.constants.statusToLabel[this.constants.status.COMPLETE];
//As the query is order by sys_updated_on, the element in the interaction is the latest one. So this gives the latest timestamp
result.timeStamp = this.setupUtil.getDate(interactions[0].sys_updated_on);
interactions.forEach(function(interaction){
if(interaction.status != self.constants.status.COMPLETE)
result.status = self.constants.statusToLabel[self.constants.status.IN_PROGRESS];
});
}
//If there is a mismatch in step count and itr count, it status can not be completed
if(itrCount > 0 && stepCount != itrCount)
result.status = self.constants.statusToLabel[self.constants.status.IN_PROGRESS];
return result;
},
/**
* insert an interaction log
* @param {object} - key/value for log record
* @return {object} - response object
*/
addInteractionLog : function(params) {
var dbController = new global.SNHelpDBController(this.constants.tables.user_interaction_log);
var sysId = dbController.create(params);
var result = {};
if(!sysId) {
result.status = 500;
result.message = gs.getMessage("Error creating record in table {0} ", this.constants.tables.user_interaction_log);
} else {
result.data = {sys_id : sysId};
result.status = 201;
}
return result;
},
/**
* update or insert interaction step for logGr.guidance_step (task/category)
* @param {object} logGr - GlideRecord object for user_interaction_log
*/
upsertInteractionStep : function(logGr) {
var interaction = this.helpGuidanceInteraction.findInteraction(logGr.guidance.toString(), true);
var interactionId = interaction && interaction.sys_id;
var stepId = logGr.guidance_step.toString();
var sysId, res, gr, query;
var params = {
action : logGr.action.toString(),
status : logGr.status.toString(),
};
if(logGr.user_input)
params.options = global.JSON.stringify({user_input : logGr.user_input.toString()});
// No interaction record found. create interaction record.
if(!interactionId) {
res = this.upsertInteraction(logGr.guidance.toString(), "custom");
interactionId = res.data && res.data.sys_id;
if(!interactionId)
gs.error("Error updating task status for task " + current.guidance_step.getDisplayValue());
}
sysId = this._upsertInteractionStep(interactionId, stepId, params);
if(!sysId) {
gs.error("Error updating task status for task " + current.guidance_step.getDisplayValue());
return;
}
// Optimise this
if(logGr.guidance_step.name.toString().indexOf("Install Plugin") == 0 && (logGr.guidance_step.task_type == "recommended" || logGr.guidance_step.task_type == "advanced")) {
gr = new GlideRecord(this.constants.tables.content);
gr.addQuery("configuration_types", "install_plugin");
gr.addQuery("guidance_step.parent", logGr.guidance_step.parent);
query = gr.addQuery("guidance_step.task_type", "basic");
if(logGr.guidance_step.task_type == "advanced")
query.addOrCondition("guidance_step.task_type", "recommended");
gr.query();
while(gr.next())
this._upsertInteractionStep(interactionId, gr.guidance_step.toString(), params);
}
},
/**
* Update or Insert interaction step for category when task status changes
* @param {object} current - GlideRecord object for current task status
*/
upsertParentStepInteraction: function(current) {
var stepGr = current.step.getRefRecord();
var currentStatus = current.status.toString();
var interactionGr = current.user_interaction.getRefRecord();
var parent = stepGr.parent.toString();
var sysId;
var params = {
related_user_interaction_step: current.getUniqueValue()
};
switch(currentStatus) {
case this.status.IN_PROGRESS :
params.status = this.status.IN_PROGRESS;
params.action = "started";
break;
case this.status.SKIPPED :
case this.status.COMPLETE :
params.status = this.getParentStepStatus(interactionGr, parent, currentStatus);
if(params.status == this.status.IN_PROGRESS)
params.action = "started";
else if(params.status == this.status.SKIPPED)
params.action = "skip";
else if(params.status == this.status.COMPLETE)
params.action = this.status.COMPLETE;
}
sysId = this._upsertInteractionStep(interactionGr.getUniqueValue(), parent, params);
if(!sysId)
gs.error("Error updating category status for task " + current.step.getDisplayValue());
},
/*
* @param {object} current - current gliderecord object for category
* @return {string | null} - sys_id of updated interaction record.
*/
updateSetupInteraction : function(current) {
var interactionGr = current.user_interaction.getRefRecord();
var setupId = interactionGr.guidance.toString();
var currentStatus = current.status.toString();
var sysId;
if(currentStatus === this.status.IN_PROGRESS)
interactionGr.status = this.status.IN_PROGRESS;
else
interactionGr.status = this.getSetupStatus(interactionGr.getUniqueValue(), setupId, currentStatus);
interactionGr.current_step = current.related_user_interaction_step.toString();
sysId = interactionGr.update();
if(!sysId)
gs.error("Error updating setup status for category " + current.step.getDisplayValue());
},
/**
* @param {string} interactionId - sys_id of help_user_interaction table record.
* @param {string} setupId - sys_id of help_guidance table record.
* @param {string} currentStatus - current category status
* @returns {string} status for help_user_interaction for setupId
*/
getSetupStatus : function(interactionId, setupId, currentStatus) {
var categories = [];
var count;
if(currentStatus === this.status.IN_PROGRESS)
return this.status.IN_PROGRESS;
var gr = new GlideRecord(this.constants.tables.guidance_step);
gr.addQuery("guidance", setupId);
gr.addNullQuery("parent");
gr.query();
while(gr.next())
categories.push(gr.getUniqueValue());
var statusGr = new GlideRecord(this.constants.tables.user_interaction_step);
statusGr.addQuery("user_interaction", interactionId);
statusGr.addQuery("step", "IN", categories.join(","));
statusGr.query();
count = statusGr.getRowCount();
// Not all the categories have corresponding interactino record. setup is in progress.
if(count < categories.length)
return this.status.IN_PROGRESS;
while(statusGr.next())
if(statusGr.status.toString() !== currentStatus)
return this.status.IN_PROGRESS;
return currentStatus;
},
/**
* update or insert interaction step
* @param {string} interactionId - sys_id of user_interaction record
* @param {string} stepId - sys_id of guidance_step (category or task)
* @params {object} params - key value map for user_interaction_step table
*
*/
_upsertInteractionStep : function(interactionId, stepId, params) {
var stepGr = this.getInteractionStep(interactionId, stepId);
var dbController;
if(stepGr) {
stepGr.action = params.action;
stepGr.status = params.status;
stepGr.related_user_interaction_step = params.related_user_interaction_step;
if(params.options)
stepGr.options = params.options;
return stepGr.update();
} else {
dbController = new global.SNHelpDBController(this.constants.tables.user_interaction_step);
params.user_interaction = interactionId;
params.step = stepId;
return dbController.create(params);
}
},
/**
* Calculate the status of the category based on tasks
* We need to check the current active setup to check what tasks we need to complete before marking
* parent category complete. For eg - for basic - all basic tasks needs to complete
* while for best_exp - basic and best_exp tasks needs to complete before marking category complete.
* in case of custom all tasks needs to complete to mark category complete.
* @param {object} integrationGr - GlideRecord for setup interaction
* @param {string} parent - sys_id of the setup category
* @param {string} currentStatus - status of the most recently updated setup task.
* @returns {string} status - status of the category
*/
getParentStepStatus : function(interactionGr, parent, currentStatus) {
var tasks = [];
var interactionId = interactionGr.getUniqueValue();
var taskTypes = "";
switch(interactionGr.active_setup_type.toString()) {
case "quick" :
taskTypes = "basic";
break;
case "best_exp":
taskTypes += "basic^ORtask_type=recommended";
break;
case "custom":
taskTypes += "basic^ORtask_type=recommended^ORtask_type=advanced";
}
var gr = new GlideRecord(this.constants.tables.guidance_step);
gr.addEncodedQuery("parent=" + parent + "^task_type=" + taskTypes);
gr.query();
while(gr.next())
tasks.push(gr.getUniqueValue());
var statusGr = new GlideRecord(this.constants.tables.user_interaction_step);
statusGr.addEncodedQuery("user_interaction=" + interactionId + "^stepIN" + tasks.join(","));
statusGr.query();
var count = statusGr.getRowCount();
// Interaction is not available for all tasks - category status is in progress.
if(count < tasks.length)
return this.status.IN_PROGRESS;
while(statusGr.next())
if(statusGr.status.toString() !== currentStatus) // if all tasks status is not same, set category to in progress
return this.status.IN_PROGRESS;
return currentStatus;
},
/**
* Check if the interaction record exist for current task/category
* (Read ACL on interaction step table restrict read to sn_help_admin.)
* @param {string} interactionId - sys_id of setup interaction record
* @param {string} step - sys_id of setup step (category/task)
* @returns {object} gr - interactionStep GlideRecord for current step or null if not exists.
*/
getInteractionStep : function(interactionId, step) {
var gr = new GlideRecord(this.constants.tables.user_interaction_step);
gr.addEncodedQuery("user_interaction=" + interactionId + "^step=" + step);
gr.query();
if(gr.hasNext() && gr.next())
return gr;
return null;
},
/**
* Create interaction record if there is no record exists.
* @param {string} guidanceId - sys_id of guidance record
* @param {string} setupType - current setup_type - quick, best_exp, advanced
* @returns {string} sys_id of newly created interaction record.
*/
upsertInteraction : function(guidanceId, setupType) {
var sysId,
params,
dbController,
interactionGr,
result = {};
if (!this.isValidSetupId(guidanceId)) {
result.status = 400;
result.message = gs.getMessage("Invalid setup Id {0}", guidanceId);
return result;
}
interactionGr = this.getInteraction(guidanceId);
if(interactionGr && interactionGr.active_setup_type.toString() != setupType) {
interactionGr.active_setup_type = setupType;
interactionGr.status = this.status.IN_PROGRESS; // setup type change, update the status
sysId = interactionGr.update();
if(sysId)
this.updateInteractionStatus(guidanceId, setupType);
} else if(!interactionGr){
dbController = new global.SNHelpDBController(this.constants.tables.user_interaction);
params = {
guidance : guidanceId,
active_setup_type : setupType,
status : this.status.NOTSTARTED,
};
sysId = dbController.create(params);
} else {
sysId = interactionGr.sys_id + "";
}
if(!sysId) {
gs.warn("Error while creating interaction record for setup " + guidanceId);
result.status = 500;
result.message = gs.getMessage("Error creating Interaction Record for setup {0}", guidanceId);
return result;
}
result.status = 200;
result.data = {sys_id : sysId};
return result;
},
/**
* Update the interaction status
*
*
*/
updateInteractionStatus : function(guidanceId, setupType) {
var categoryIds = [];
switch(setupType) {
case "quick" :
setupType = "basic";
break;
case "best_exp" :
setupType = "recommended";
break;
case "custom" :
setupType = "advanced";
break;
}
var gr = new GlideRecord(this.constants.tables.guidance_step);
gr.addQuery("guidance", guidanceId);
gr.addQuery("task_type", setupType);
gr.addQuery("type", "activity");
gr.query();
while(gr.next()){
categoryIds.push(gr.parent.toString());
}
gr = new GlideRecord(this.constants.tables.user_interaction_step);
gr.addQuery("step", "IN", categoryIds.join(","));
gr.status = this.status.IN_PROGRESS;
gr.updateMultiple();
},
getInteraction : function(guidanceId) {
var gr = new GlideRecord(this.constants.tables.user_interaction);
gr.addQuery("guidance", guidanceId);
gr.query();
if(gr.hasNext() && gr.next())
return gr;
return null;
},
/**
Moved from Guidance step controller
Return a step for given sys_id
@param : step sys_id
@returns : Single guidance step for given sys_id
*/
getSetupStep : function(sys_id) {
var step, content;
if (!sys_id) {
this.helpUtil.setError(this.type,this.helpConstants.errorMessages.empty_sys_id);
return null;
}
dbController = new global.SNHelpDBController(this.constants.tables.guidance_step);
step = dbController.getById(sys_id, this.constants.restAPIKeys.setupStep);
if(step) {
content = this.helpContent.getContent(step.sys_id, step.layout, this.constants.restAPIKeys.setupContent) || {};
if(Array.isArray(content) && content.length > 0) {
step.content = content[0];
if(step.content.related_content)
step.content.related_content = this.getRelatedContent(step.content.related_content);
} else {
step.content = content;
}
//This is a explict check to fetch pluigns (basic, recommended, advacned)
if(step.content && step.content.configuration_types=="install_plugin") {
step.content.records = this.getPluginsDetails(step.content.records);
if(step.content.records) {
var pluginTasks = this.setupUtil.getPluginTasks(step.guidance, step.parent);
var i;
var self = this;
switch(step.task_type) {
case this.constants.taskType.BASIC :
step.content.records.forEach(function(record) {
record.taskType = self.constants.taskType.BASIC;
});
for(i = 0; i < pluginTasks.length; i++) {
if(pluginTasks[i].task_type === this.constants.taskType.ADVANCED){
step.description = pluginTasks[i].description;
step.rich_description = pluginTasks[i].rich_description;
}
}
break;
case this.constants.taskType.RECOMMENDED :
for(i = 0; i < pluginTasks.length; i++) {
if(pluginTasks[i].task_type === this.constants.taskType.BASIC) {
step.content.records.forEach(function(record) {
if(pluginTasks[i].content.records.indexOf(record.sys_id) >= 0)
record.taskType = self.constants.taskType.BASIC;
});
} else {
step.content.records.forEach(function(record) {
if(!record.taskType)
record.taskType = self.constants.taskType.RECOMMENDED;
});
}
if(pluginTasks[i].task_type === this.constants.taskType.ADVANCED){
step.description = pluginTasks[i].description;
step.rich_description = pluginTasks[i].rich_description;
}
}
break;
case this.constants.taskType.ADVANCED :
for(i = 0; i < pluginTasks.length; i++) {
if(pluginTasks[i].task_type === this.constants.taskType.BASIC) {
step.content.records.forEach(function(record) {
if(pluginTasks[i].content.records.indexOf(record.sys_id) >= 0)
record.taskType = self.constants.taskType.BASIC;
});
} else if(pluginTasks[i].task_type === this.constants.taskType.RECOMMENDED) {
step.content.records.forEach(function(record) {
if(pluginTasks[i].content.records.indexOf(record.sys_id) >= 0 && !record.taskType)
record.taskType = self.constants.taskType.RECOMMENDED;
});
} else {
step.content.records.forEach(function(record) {
if(!record.taskType)
record.taskType = self.constants.taskType.ADVANCED;
});
}
}
break;
}
}
}
}
return step;
},
/**
Returns plugin deatils
@param : pluginIds - string with comma separated sys_id of plugin id's
@returns : array of plugin deaitls (id, name, installed status)
*/
getPluginsDetails: function(pluginIds){
var results = [], result = {}, gr;
if(!pluginIds)
return null;
gr = new GlideRecord(this.constants.tables.plugin);
gr.addEncodedQuery("sys_idIN"+pluginIds);
gr.query();
while(gr.next()){
result = {};
result.id = gr.getValue("id");
result.sys_id = gr.getValue("sys_id");
result.name = gr.getValue("name");
result.active = gr.getValue("active");
result.description = gr.getValue("description");
results.push(result);
}
return results;
},
/* Reoreders steps within same category or moves step from source to destination category.
* Move:
* When moving step from one category to another, we move the step to destinationCategory
* with order set as -1. This ensures that the step is always at the top and then adjustStepOrder is called.
*
* Reorder:
* The source order (current order) of step and destinationOrder is passed to adjustStepOrder
*/
reorderStep: function(setupId, data) {
var destinationCategory = data.destination_category;
var step = data.step;
var sourceCategory = data.source_category;
var destinationOrder = data.destination_order;
var type = data.type;
var parent, result;
var dbController = new global.SNHelpDBController(this.constants.tables.guidance_step);
var dbStep = dbController.getById(step, ["sys_id", "order", "name", "type"]);
var prevOrder = dbStep.order;
// verify step
if (!dbStep) {
return {
status: 400,
message: gs.getMessage("Invalid step sys_id {0}", step)
};
}
if (type == this.constants.stepType.GROUP) {
// if step is a category
parent = setupId;
} else
parent = sourceCategory;
if (!this.verifyStepParent(step, parent, type)) {
return {
status: 404,
message: gs.getMessage("Step not child of source category")
};
}
// in case of moving task from one category to another
if (type != this.constants.stepType.GROUP && sourceCategory != destinationCategory) {
result = this.upsertStep(step, {
parent: destinationCategory,
order: -1,
type: dbStep.type,
name: dbStep.name
});
if (result.status != 200) {
return {
status: result.status,
message: result.message
};
}
// source order is 0 as we moved the step and set its order as -1
result = this.adjustStepsOrder(setupId, type, destinationCategory, 0, destinationOrder - 1);
if (result.status != 200) {
return {
status: result.status,
message: result.message
};
}
// sourceOrder and destinationOrder are -1 as we don't have to splice any element. We just have to
// adjust orders of existing steps
result = this.adjustStepsOrder(setupId, type, sourceCategory, -1, -1);
if (result.status != 200) {
return {
status: result.status,
message: result.message
};
}
} else {
var sourceOrder = parseInt(dbStep.order);
// adjust order of steps in destination category
result = this.adjustStepsOrder(setupId, type, parent, sourceOrder - 1, destinationOrder - 1);
if (result.status != 200) {
return {
status: result.status,
message: result.message
};
}
}
var dependencyService = new SNHelpSetupDependencyService();
dependencyService.handleDependencyConflict(step, type, prevOrder, sourceCategory);
return {
status: 200,
message: gs.getMessage("Steps reordered")
};
},
verifyStepParent: function(stepId, parentId, type) {
var dbController = new global.SNHelpDBController(this.constants.tables.guidance_step);
var parent, step;
if (type == this.constants.stepType.GROUP) {
step = dbController.getById(stepId, ["guidance"]);
parent = step.guidance;
} else {
step = dbController.getById(stepId, ["parent"]);
parent = step.parent;
}
if (parent == parentId)
return true;
return false;
},
/*
* Adjust orders of steps of setup after reorder or move.
* Get all the child steps of parent step as in array. Remove the step from sourceOrder and place it at
* destinationOrder.
* @params: sourceOrder - order of step before it is moved to destinationOrder
* @params: destinationOrder - order of step where it has to be placed at
*/
adjustStepsOrder: function(setupId, type, parent, sourceOrder, destinationOrder) {
// get all steps
var queryString;
var orderBy = "order";
var fields = ["sys_id", "order", "name", "type"];
var dbController = new global.SNHelpDBController(this.constants.tables.guidance_step);
if (type == this.constants.stepType.GROUP)
queryString = "parentISEMPTY";
else
queryString = "parent=" + parent;
queryString += "^guidance=" + setupId + "^type=" + type;
var steps = dbController.getByEncodedQuery(queryString, orderBy, fields);
var stepOrder, result;
// reorder all steps
if (sourceOrder != -1 && destinationOrder != -1) {
var toMove = steps[sourceOrder];
steps.splice(sourceOrder, 1);
steps.splice(destinationOrder, 0, toMove);
}
for (var step = 0; step < steps.length; step++) {
if (parseInt(steps[step].order) != step + 1) {
result = this.upsertStep(steps[step].sys_id, {
order: step + 1,
name: steps[step].name,
type: steps[step].type
});
if (result.status != 200) {
return {
status: result.status,
message: result.message
};
}
}
}
return {
status: 200
};
},
/**
* Configure plugins for individual setup type - basic, recommended and advanced
* @params {string} setupId
* @params {string} pluginCategory
* @params {object} params - configuration object with individual plugins details.
* @returns {object} result - configuration object with individual plugins details.
*/
configurePluginsForSetupType : function(setupId, pluginCategory, params) {
var pluginTasks = this.setupUtil.getPluginTasks(setupId, pluginCategory);
var config = {};
var setupType = ["basic", "recommended"];
var DONE = "0"; // status of the task creation
if(pluginTasks.length <= 1) {
for(key in setupType) {
config.task_type = setupType[key];
config.status = DONE;
config.records = params[setupType[key]] || "";
config.description = "Plugins for "+config.task_type;
if(Array.isArray(config.records))
config.records = config.records.join(",");
this.createInstallPluginTask(setupId, pluginCategory, config);
}
} else {
for(var i = 0; i < pluginTasks.length; i++) {
if(pluginTasks[i].task_type == "basic" || pluginTasks[i].task_type == "recommended") {
config.records = params[pluginTasks[i].task_type];
if(Array.isArray(config.records))
config.records = config.records.join(",");
if(config.records && config.records != pluginTasks[i].records) {
config.sys_id = pluginTasks[i].content.sys_id;
this.updateContent(config);
}
}
}
}
return this.getPluginsBySetupType(setupId, pluginCategory);
},
/**
* Gets the plugins details by setup type
* @params {string} setupId - sys_id of setup
* @params {string} pluginCategory - sys_id of plugin category
* @returns {object} result - configuration object with individual plugins details.
*/
getPluginsBySetupType: function(setupId, pluginCategory) {
var taskType,
resp = {
basic : [],
recommended : [],
advanced : []
},
result = {};
var gr = new GlideRecord(this.constants.tables.content);
gr.addQuery("guidance_step.parent", pluginCategory);
gr.addQuery("configuration_types", "install_plugin");
gr.query();
while(gr.next()) {
taskType = gr.guidance_step && gr.guidance_step.task_type.toString();
resp[taskType] = gr.records.toString() ? gr.records.toString().split(",") : [];
}
resp.setupId = setupId;
resp.pluginCategory = pluginCategory;
result.status = 200;
result.data = resp;
return result;
},
isCategoryforPlugins: function(categoryId){
var dbController, query, contents;
query = 'configuration_types=install_plugin^guidance_step.parent='+categoryId;
dbController = new global.SNHelpDBController(this.constants.tables.content);
contents = dbController.getByEncodedQuery(query, '', ['configuration_types']);
if(Array.isArray(contents) && contents.length > 0)
return true;
return false;
},
type: 'SNHelpSetupService'
};
Sys ID
a9caf20a70333010f877d3e7afe0eeaf