// PhantomJS doesn't support bind yet
Function.prototype.bind = Function.prototype.bind || function (thisp) {
var fn = this;
return function () {
return fn.apply(thisp, arguments);
};
};
import Protocols from './protocols.js'
import Wizard from './wizard.js'
class SmartOrg {
/**
* Any interaction with the SmartOrg API starts by creating a SmartOrg object.
* @example
* // If your API is at https://localhost/kirk
* var endpoint = "https://localhost";
* var path = "kirk";
* var smartorg = new SmartOrg(endpoint, path);
*
* @param {string} endpoint The SmartOrg server endpoint
* @param {string} path_ The path where the API is accessible
*/
constructor(endpoint, path_) {
this.protocols = new Protocols(endpoint, path_, this);
this.wizard = new Wizard(this.protocols);
console.info("SmartOrg Javascript API.");
console.log("Manhattan Build");
console.log("version 2.2");
this.networkErrorHandler = null;
}
onNetworkError(callBackFunction) {
this.networkErrorHandler = callBackFunction;
}
/** @typedef {object} UserInfo
* @property {string} uid - User ID generated from server
*/
/**
* @external Promise
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise Promise}
*/
/**
* This callback is called when the result is loaded.
*
* @callback PromiseAuthenticateCallbackSuccess
* @param {UserInfo} ret - The result is loaded.
*/
/**
* This callback is called when the result fails to load.
*
* @callback PromiseAuthenticateCallbackError
* @param {Error} err - The error that occurred while loading the result.
*/
/** Resolves with a {@link PromiseAuthenticateCallbackSuccess}, fails with a {@link PromiseAuthenticateCallbackError}
*
* @typedef {Promise} PromiseAuthenticate
*/
/**
* Authenticate the user using the credentials provided.
* This is the first thing that needs to happen after the SmartOrg object
* has been created.
*
* @param {Object} credentials The credentials with which the user is to be authenticated.
* @param {string} credentials.username The username
* @param {string} credentials.password The password
* @returns {PromiseAuthenticate} A promise to authenticate
*
* @example
* // Let's assume the SmartOrg API is accessible at https://localhost/kirk
* var smartorg = new SmartOrg("https://localhost","kirk");
* var username = ...; // get the username from somewhere
* var password = ...; // get the password from somewhere
* smartorg.authenticate({'username': username, 'password': password})
* .then(function (userInfo) {
* console.info("user ID " + userInfo.uid + " logged in");
* })
* .catch(function (err) {
* console.error("Error occurred "+err);
* });
*/
authenticate(credentials) {
this.protocols.makeCredentials(credentials);
var path_ = this.protocols._getPath('framework/login');
path_ = `${path_}/${credentials.username}`;
return this.protocols.apiGet(path_);
}
/** @typedef {object} Template
* @property {string} name - Name of this template
* @property {string} hasPlatform - Does this template have a platform capability?
* @property {object} [info] - Information about this template
* @property {string} [info.Creator] - Name of the creator of this template
* @property {string} [info.CreatorLink] - Link to the template creator's website
* @property {string} [info.Description] - Description of this template
* @property {string} [info.Email] - Email id of template creator
*/
/**
* @external Promise
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise Promise}
*/
/**
* This callback is called when the result is loaded.
*
* @callback PromiseTemplatesCallbackTemplateSuccess
* @param {Template[]} ret - The result is loaded.
*/
/**
* This callback is called when the result fails to load.
*
* @callback PromiseTemplatesCallbackTemplateError
* @param {Error} err - The error that occurred while loading the result.
*/
/** Resolves with a {@link PromiseTemplatesCallbackTemplateSuccess}, fails with a {@link PromiseTemplatesCallbackTemplateError}
*
* @typedef {Promise} PromiseTemplates
*/
/**
* Obtain all the templates applicable to a node.
* @param {string} nodeID The ID of the node for which templates are to be fetched.
* Normally, this would result in all the templates in the system, unless the administrator has restricted
* the templates that are visible in the portfolio of which this node is a part. In that case,
* only the restricted templates will be returned.
* @returns {PromiseTemplates} A promise to provide the list of templates
* @example
* smartorg.templatesFor(templatesNodeID)
* .then(function (ret) {
* console.warn(ret);
* // ret[0] --> First Template
* // ret[0].name --> Name of first template
* // ret[0].hasPlatform --> Does this have a platform?
* // ret[0].info.Creator --> Optional name of creator of template
* // ret[0].info.CreatorLink --> Optional link to creator website
* // ret[0].info.Description --> Optional description of template
* // ret[0].info.Email --> Optional email id of creator of template
* })
* .catch(function (err) {
* console.error(err);
* })
*/
templatesFor(nodeID) {
var path_ = this.protocols._getPath('domain/templates');
path_ = `${path_}/${nodeID}`;
return this.protocols.apiGet(path_);
}
/**
* Get all templates. Maybe duplicated to templatesFor when node
* id is empty.
*
* @returns {*}
*/
getAllTemplates() {
var path_ = this.protocols._getPath('domain/alltemplates');
path_ = `${path_}`;
return this.protocols.apiGet(path_);
}
/**
* @typedef {object} AclGroup
* @property {Array<string>} editors - Array of user ids of editors
* @property {Array<string>} portfolioAdmins - Array of user ids of portfolio administrators
* @property {Array<string>} viewers - Array of user ids of viewers
*/
/**
* @typedef {object} Acl
* @property {AclGroup} group - Group Access Control List
* @property {string} owner - User ID of owner of portfolio
* @property {AclGroup} user - What's this for?
*/
/**
* @typedef {object} Node
* @property {string} name - Name of this node
* @property {string} _id - ID of this node
* @property {string} _rev - Revision number of this node
* @property {string} data - A pointer to the data node of the portfolio
* @property {string} treeID - The name of the tree to which this node belongs
* @property {Array<string>} children - An array of child node IDs under this node
* @property {Array<string>} commands - An array of templates that apply to this node. Portfolio nodes tend not to have commands, so this array is likely 0 for such nodes. If there is a template, then only the first item in this array would be populated. This has been kept an array just in case the design evolves to support multiple templates for a node.
* @property {boolean} isPlatform - Is the current node a platform node? This is always false for portfolio nodes.
* @property {Acl} [acl] - The access control list information for this portfolio. This attribute is only present if the node is a root (portfolio) node.
*/
/**
* @external Promise
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise Promise}
*/
/**
* This callback is called when the result is loaded.
*
* @callback PromisePortfoliosCallbackSuccess
* @param {Node[]} ret - A collection of root (or portfolio) nodes that the user is allowed to access.
*/
/**
* This callback is called when the result fails to load.
*
* @callback PromisePortfoliosCallbackError
* @param {Error} err - The error that occurred while loading portfolios.
*/
/** Resolves with a {@link PromisePortfoliosCallbackSuccess}, fails with a {@link PromisePortfoliosCallbackError}
*
* @typedef {Promise} PromisePortfolios
*/
/**
* Fetches all the portfolios available to user, based on access control rules
* setup by the administrator. If no rules are set for the user, all
* portfolios will be returned.
*
* @returns {PromisePortfolios} A promise to the portfolios
* @example
* smartorg.portfolios()
* .then(function (portfolios) {
* portfolios.map(function (portfolio) {
* console.log(portfolio);
* })
* })
* .catch(function (err) {
* console.error(err);
* })
*/
portfolios() {
var path_ = this.protocols._getPath('template/portfolios');
return this.protocols.apiGet(path_);
}
/** @typedef {object} Input
* @property {string} Key The key of this input
* @property {string} Type The type of this input (SCALAR|DISTRIBUTION|TABLE)
* @property {string} Units The units of this input
* @property {string} Display The display prompt of this input
* @property {string} Description The description of this input
* @property {string} Constraint The constraint placed on this input (double|integer|year|date|text)
* @property {string} Val The value of this input
* @property {boolean} Inherited Is this an inherited input (shared variable)?
* @property {string} InputType Is this data local to the node or overridden? (LOCAL|OVERRIDE)
* @property {number} isLeaf If this node is a leaf, this is set to 1 otherwise 0
* @property {string} CellLink The link to the Excel cell
*/
/** @typedef {object} MenuItems
* @property {string} nodeAttribute - This has identifiers like "r" or "rw" to specify if this node is editable.
* @property {string} nodeID - The node for which the inputs have been fetched
* @property {Input[]} inputs - The inputs that have been found
* @property {string} selectedInputKey - what is this?
* @property {string} targetDS - The dataset ID. Why is it called "target"?
* @property {string} templateID - The ID of the template associated with this node
* @property {string} user - The name of the user who has made the request
*/
/**
* @external Promise
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise Promise}
*/
/**
* This callback is called when the result is loaded.
*
* @callback PromiseInputsCallbackSuccess
* @param {MenuItems} ret - A collection of inputs matching the keys at the node
*/
/**
* This callback is called when the result fails to load.
*
* @callback PromiseInputsCallbackError
* @param {Error} err - The error that occurred while loading inputs.
*/
/** Resolves with a {@link PromiseInputsCallbackSuccess}, fails with a {@link PromiseInputsCallbackError}
*
* @typedef {Promise} PromiseInputs
*/
/**
* Given the keys for inputs and a node ID, all the input data
* at that node matching the keys are fetched.
*
* @param {string} nodeID The ID of the node at which the inputs are to be fetched
* @param {string} inputKeys A pipe-delimited list of input keys that are to be fetched at the node
* @returns {PromiseInputs} A promise to the inputs
* @example
* nodeID = "012345";
* inputKeys = "marketSize|marketShare|discountRate";
* smartorg.inputsFor(nodeID, inputKeys)
* .then(function (inputs) {
* inputs.menuItems.map(function (input) {
* console.log(input);
* })
* })
* .catch(function (err) {
* console.error(err);
* })
*/
inputsFor(nodeID, inputKeys) {
var path_ = this.protocols._getPath('template/inputs');
path_ = `${path_}/${nodeID}/${encodeURIComponent(inputKeys)}`;
return this.protocols.apiGet(path_);
}
/** @typedef {object} CompareValueChildData
* @property {Array<string>} childLeafNames - A list of names of all children immediately below the selected node
* @property {Array<object>} compareValueData - A list of values of all children immediately below the selected node. The values are picked from the template (portfolio or platformPortfolio) based on the *Keys* parameter (an array of output keys) for the COMPARE_VALUE command.
* @property {string} nodeName - Name of the selected node
*/
/** @typedef {object} CompareValueData
* @property {object} commandJSON - This has attributes that setup the chart display
* @property {CompareValueChildData} highlightedNode - This is the appropriate value data in the node that has been selected
* @property {CompareValueChildData} siblingNode - This is the appropriate value data in the sibling node that has been selected. It will be *null* if no sibling has been selected.
*/
/** @typedef {object} CompareUncOutputData
* @property {string} Display - Full display describing the output
* @property {string} Units - Units of the output
* @property {number} Mean - The mean value of the combined uncertainty bar of this output in the Tornado
* @property {string} NodeName - Name of the child
* @property {Array<number>} Summary - The low (0), medium (1) and high (2) values of this output based on the combined uncertainty bar in the Tornado.
*/
/** @typedef {object} CompareUncData
* @property {Array<Array<CompareUncOutputData>>} highlightedNode - This is a nested array. First, it has as many elements as there are children. Each element is an array of outputs, one for each Tornado *ValueMetricKey*.
* @property {Array<Array<CompareUncOutputData>>} siblingNode - This is a nested array. First, it has as many elements as there are children. Each element is an array of outputs, one for each Tornado *ValueMetricKey*. An empty array is returned if no sibling has been selected.
* @property {string} nodeName - Node name of highlighted node
* @property {string} shadowNodeName - Node name of sibling node. This is null if no sibling has been selected.
*/
/**
* This callback is called when the result is loaded.
*
* @callback PromiseActionCallbackSuccess
* @param {(CompareValueData|CompareUncData)} ret - An object that differs based on the command that was executed
*/
/**
* This callback is called when the result fails to load.
*
* @callback PromiseActionCallbackError
* @param {Error} err - The error that occurred while loading inputs.
*/
/** Resolves with a {@link PromiseActionCallbackSuccess}, fails with a {@link PromiseActionCallbackError}
*
* @typedef {Promise} PromiseActionResults
*/
/**
* Executes action command and fetches the results. This is a general way to access any template menu command.
*
* @param {string} actionID - The ID for the action specified in the template menu JSON (portfolio or application structure).
* @param {string} nodeID - The node for which the action is to be applied
* @param {object} packedReportOptions - Report options for this action.
* @returns {PromiseActionResults} A promise to the result of running the action
* @example
* smartorg.actionFor(actionID, nodeID)
* .then(function (data) {
* console.log(data); // The data object is structured differently for each command
* })
* .catch(function (err) {
* console.error(err);
* })
*/
actionFor(actionID, nodeID, packedReportOptions) {
var path_ = this.protocols._getPath('template/actionMenu');
path_ = `${path_}/${actionID}/${nodeID}/${packedReportOptions}`;
return this.protocols.apiGet(path_);
}
/** @typedef {object} MenuObject
* @property {string} Command - The command to be invoked by this action
* @property {string} displayText - The display for this menu item
* @property {string} menuID - The unique key for this menu item
* @property {string} nodeID - The node ID for from this menu item has been fetched
* @property {boolean} isOutput - Is this command an output command? *TABLE_INPUT* and *INPUT_SCREEN* are input commands, and all else are output commands.
* @property {number} level - What is this?
* @property {object} parameters - These specify what needs to go into the command. They differ based on the command.
* @property {string} A - Legacy Javascript code injection. Ignore when writing your applications.
*/
/**
* This callback is called when the result is loaded.
*
* @callback PromiseActionMenuCallbackSuccess
* @param {Object} menu - An object that contains the menu items
* @param {Object} menu.menuItems - The menu items for the node
* @param {Array<MenuObject>} menu.menuItems.Actions - The menu items under the "Actions" section
* @param {Array<MenuObject>} menu.menuItems.Management - The menu items under the "Management" section
*/
/**
* This callback is called when the result fails to load.
*
* @callback PromiseActionMenuCallbackError
* @param {Error} err - The error that occurred while loading inputs.
*/
/** Resolves with a {@link PromiseActionMenuCallbackSuccess}, fails with a {@link PromiseActionMenuCallbackError}
*
* @typedef {Promise} PromiseActionMenu
*/
/**
* Fetches the menu (from the appropriate template) that is associated with a node.
*
* @param {string} nodeID The ID of the node for which a menu is to be fetched
* @returns {PromiseActionMenu} A promise to return the action menu for the specified node
* @example
* smartorg.actionMenuFor(nodeID)
* .then(function (menu) {
* console.log(menu);
* })
* .catch(function (err) {
* handleError(err);
* });
*/
actionMenuFor(nodeID) {
var path_ = this.protocols._getPath('template/actionMenu');
path_ = `${path_}/${nodeID}`;
return this.protocols.apiGet(path_);
}
/**
* Get share data (Input screen) structure.
*
* @param nodeID {string} Tree node ID.
* @returns {Promise} A promise to return shared data for the
* specified node.
* @example
* smartorg.sharedDataFor(nodeID)
* .then(function (menu) {
* console.log(menu);
* })
* .catch(function (err) {
* handleError(err);
* });
*/
sharedDataFor(nodeID) {
var path_ = this.protocols._getPath('template/sharedData');
path_ = `${path_}/${nodeID}`;
return this.protocols.apiGet(path_);
}
/**
* @typedef {object} InputKeyValPair
* @property {string} Key - the key of the input, eg startYear or discountRate
* @property {string} Val - the value of the input eg 0.89
*/
/**
* Saves inputs
* @param {string} nodeID The ID of the node that's inputs are to be saved
* @param {Array<InputKeyValPair>} inputs array of inputs to be saved
* @returns {string} msg - save status message
* @example saved dataset for node 'leafNodeExample' by calling template 'exampleTemplateName'
* @example
*
* //to save inputs for a given node
* smartorg.saveInputs(nodeID, inputs)
* .then(function (ret) {
* console.log(ret); // Need documentation on ret
* })
* .catch(function (err) {
* handleError(err);
* });
*/
saveInputs(nodeID, inputs) {
var path_ = this.protocols._getPath('domain/template');
var body_ = {
nodeID: nodeID,
inputs: inputs
};
return this.protocols.apiPut(path_, body_);
}
overrideInput(targetNodeID, sourceNodeID, inputKey) {
var path_ = this.protocols._getPath('domain/overrideInput');
var body_ = {
'targetNodeID': targetNodeID,
'sourceNodeID': sourceNodeID,
'inputKey': inputKey
};
return this.protocols.apiPut(path_, body_);
}
deoverrideInput(targetNodeID, inputKey) {
var path_ = this.protocols._getPath('domain/deoverrideInput');
var body_ = {
targetNodeID: targetNodeID,
inputKey: inputKey
};
return this.protocols.apiPut(path_, body_);
}
/**
* This callback is called when the Paste Node succeeds
*
* @callback PromisePasteStatusCallbackSuccess
* @param {Number} status - 0=success non-zero=failure
* @param {string} message - e.g. 'pasted data'
*/
/**
* This callback is called when the Paste Node fails
*
* @callback PromisePasteStatusCallbackError
* @param {Number} status - http status code, e.g. 500
* @param {string} statusText -http status text, e.g. 'INTERNAL SERVER ERROR'
* @param {string} message - e.g. incorrect _id 'ERROR PasteNode Exception ('_id')'
*/
/** Resolves with a {@link PromisePasteStatusCallbackSuccess}, fails with a {@link PromisePasteStatusCallbackError}
*
* @typedef {Promise} PromisePasteStatus
*/
/**
* Paste Node
* @param {string} targetParentNodeID parent Node ID
* @param {string} nodeToPaste Node ID to paste
* @returns {PromisePasteStatus} A promise to provide status message of the Paste Node operation.
*
* @example
* // to paste a node under a target parent node
* smartorg.pasteNode(targetParentNodeID, nodeToPaste)
* .then(function (ret) {
* console.warn(ret);
* })
*.catch(function (err) {
* handleError(err);
* })
*/
pasteNode(targetParentNodeID, nodeToPaste) {
var path_ = this.protocols._getPath('domain/paste');
path_ = `${path_}/${targetParentNodeID}/${nodeToPaste}`;
return this.protocols.apiGet(path_);
}
/**
* Set a node (and its children) readonly
* @param nodeID
* @param includeAllChildren
* @returns {string} msg - Made node (and its descendants) readonly
* @example
* smartorg.makeReadOnly(nodeID, includeAllChildren)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
makeReadOnly(nodeID, includeAllChildren) {
var path_ = this.protocols._getPath('domain/readonly');
var attribute = "r";
path_ = `${path_}/${nodeID}/${attribute}/${includeAllChildren}`;
return this.protocols.apiPost(path_, {});
}
/**
* Set a node (and its children) editable
* @param nodeID
* @param includeAllChildren
* @returns {string} msg - Made node (and its descendants) editable
* @example
* smartorg.makeEditable(nodeID, includeAllChildren)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
makeEditable(nodeID, includeAllChildren) {
var path_ = this.protocols._getPath('domain/readonly');
var attribute = "rw";
path_ = `${path_}/${nodeID}/${attribute}/${includeAllChildren}`;
return this.protocols.apiPost(path_, {});
}
/**
* Fetch change log at or under current node.
*
* @param {string} nodeID - The ID of the node at or under which change log is to be fetched
* @returns {Array<changes>}
*/
changeLog(nodeID) {
var path_ = this.protocols._getPath('domain/changes');
path_ = `${path_}/${nodeID}`;
return this.protocols.apiPost(path_, {});
}
/**
* Recalculate entire portfolio
* @param treeID
* @param recalType
* @param startNodeId
* @returns {string} msg - tree is recalculated
* @example
* smartorg.recalculatePortfolio(treeID)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
recalculatePortfolio(treeID, recalType, startNodeId) {
var path_ = this.protocols._getPath('domain/recalculate');
path_ = `${path_}/${encodeURIComponent(treeID)}`;
var body_ = {
recalType: recalType,
startNodeId: startNodeId
};
return this.protocols.apiPost(path_, body_);
}
/**
* Get the total number of orphan nodes in tree.
*
* @param treeID {string} Tree id aka root node name.
* @returns {*|Promise.<T>|Promise|axios.Promise}
* then: number of nodes.
*/
getOrphanNodesCount(treeID) {
var path_ = this.protocols._getPath('domain/tree/analyse/orphan');
path_ = `${path_}/${encodeURIComponent(treeID)}`;
return this.protocols.apiGet(path_);
}
/**
* Fix (delete) all orphan nodes in tree.
*
* @param treeID {string} Tree id aka root node name.
* @returns {*|Promise.<T>|Promise|axios.Promise}
* then: number of deleted nodes.
*/
fixOrphanNodesCount(treeID) {
var path_ = this.protocols._getPath('domain/tree/analyse/orphan');
path_ = `${path_}/${encodeURIComponent(treeID)}`;
return this.protocols.apiDelete(path_);
}
/**
* Get calculation engine version number and log level.
*
* @return {{}} Promise.
* then: {logLevel: "something", versionNumber: "something"}
* catch: Error.
*/
getCalculationEngineInfo() {
var path_ = this.protocols._getPath('domain/calcengine/version');
return this.protocols.apiGet(path_);
}
/**
* Fetch lines from bottom of calculation engine log
* @param linesFromBottom
* @returns {string} msg - fetched lines from bottom of calculation engine log
* @example
* smartorg.fetchCalculationEngineLog(treeID)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
fetchCalculationEngineLog(linesFromBottom) {
var path_ = this.protocols._getPath('domain/fetchCalculationEngineLog');
path_ = `${path_}/${linesFromBottom}`;
return this.protocols.apiGet(path_);
}
/**
* Export portfolio
* @param nodeID
* @returns {string} msg - entire portfolio is exported
* @example
* smartorg.exportPortfolio(treeID)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
exportPortfolio(nodeID) {
var path_ = this.protocols._getPath('domain/exportPortfolio');
path_ = `${path_}/${nodeID}`;
return this.protocols.apiPost(path_, {});
}
/**
* Fetch all exported portfolio paths
* @returns {string} exported portfolio path list
* @example
* smartorg.fetchAllExportedPortfolioPaths(treeID)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
fetchAllExportedPortfolioPaths() {
var path_ = this.protocols._getPath('domain/fetchAllExportedPortfolioPaths');
path_ = `${path_}`;
return this.protocols.apiGet(path_);
}
/**
* Import portfolio
* @param includeData
* @param pathToImportFiles64
* @param newTreeName64
* @returns {string} msg - portfolio is imported
* @example
* smartorg.exportPortfolio(treeID)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
importPortfolio(includeData, pathToImportFiles64, newTreeName64) {
var path_ = this.protocols._getPath('domain/importPortfolio');
path_ = `${path_}/${includeData}/${pathToImportFiles64}/${newTreeName64}`;
return this.protocols.apiPost(path_, {});
}
/**
* Create new Portfolio
* @param {string} newPortfolioName Name of the new portfolio
* @returns {string} msg - create Portfolio status message
* @example
* smartorg.createPortfolio(newPortfolioName)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
createPortfolio(newPortfolioName) {
var path_ = this.protocols._getPath('domain/tree');
path_ = `${path_}/${encodeURIComponent(newPortfolioName)}`;
var body_ = {};
return this.protocols.apiPost(path_, body_);
}
/**
* Create new Portfolio from existing portfolio
* @param {string} newPortfolioName Name of the new portfolio
* @param categoriesConfig
* @param acl
* @param chosenTemplates
* @param chosenGroups
* @returns {string} msg - create Portfolio status message
* @example
* smartorg.createPortfolioFromExisting(newPortfolioName, categoriesConfig, acl)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
createPortfolioFromExisting(newPortfolioName, categoriesConfig, acl, chosenTemplates, chosenGroups) {
var path_ = this.protocols._getPath('domain/portfolio');
var body_ = {
treeID: newPortfolioName,
categoriesConfig: categoriesConfig,
acl: acl,
chosenTemplates: chosenTemplates,
chosenGroups: chosenGroups
};
return this.protocols.apiPost(path_, body_);
}
/**
* Create a new Node under an existing portfolio
* @param {string} parentNodeID parent node ID
* @param {string} newNodeName new Node name
* @param {string} templateName template name
* @param {string} platformOrLeaf 'platform' or 'leaf'
* @returns {string} msg - create Node status message
* @example
* smartorg.createNode(parentNodeID, newNodeName, templateName, platformOrLeaf)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
createNode(parentNodeID, newNodeName, templateName, platformOrLeaf) {
var path_ = this.protocols._getPath('domain/node');
var body_ = {
nodeID: parentNodeID,
newNodeName: newNodeName,
templateName: templateName,
platformOrLeaf: platformOrLeaf
};
return this.protocols.apiPost(path_, body_);
}
/**
* This callback is called when the node is loaded.
*
* @callback PromiseNodeCallbackSuccess
* @param {Node} node - The node object
*/
/**
* This callback is called when the result fails to load.
*
* @callback PromiseNodeCallbackError
* @param {Error} err - The error that occurred while reading node.
*/
/** Resolves with a {@link PromiseNodeCallbackSuccess}, fails with a {@link PromiseNodeCallbackError}
*
* @typedef {Promise} PromiseNodeResults
*/
/**
* Retrieves a node by its ID
* @param {string} nodeID The ID of the node to get
* @returns {PromiseNodeResults} A promise to return the node
* @example
* smartorg.nodeBy(nodeID)
* .then(function (node) {
* console.log(node);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
nodeBy(nodeID) {
var path_ = this.protocols._getPath('domain/node');
path_ = `${path_}/${nodeID}`;
return this.protocols.apiGet(path_);
}
/**
* Edit Node
* @param {string} nodeID The ID of the node to edit
* @param {string} newNodeName The new node name
* @param {string} templateName The template name
* @param {Array<string>} children List of children ids.
* @returns {axios.Promise}
* @example
* smartorg.editNode(nodeID, newNodeName, templateName)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*
*/
editNode(nodeID, newNodeName, templateName, children) {
var path_ = this.protocols._getPath('domain/node');
var body_ = {
nodeID: nodeID,
newNodeName: newNodeName,
templateName: templateName,
children: children
};
return this.protocols.apiPut(path_, body_);
}
/**
* Delete Node
* @param {string} nodeID The ID of the node to delete
* @returns {string} msg - delete status message
* @example
* smartorg.deleteNode(nodeToDeleteID)
* .then(function (ret) {
* console.warn(ret);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
deleteNode(nodeID) {
var path_ = this.protocols._getPath('domain/node');
path_ = `${path_}/${nodeID}`;
return this.protocols.apiDelete(path_);
}
/**
* Tornado Report
* @param {string} nodeID The ID of the node for the Tornado
* @returns {*} tornadoData in JSON
* @example
* smartorg.tornado(nodeID)
* .then(function (tornado) {
* console.log(tornado);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
tornado(nodeID) {
var path_ = this.protocols._getPath('template/tornado');
path_ = `${path_}/${nodeID}`;
return this.protocols.apiGet(path_);
}
/**
* This callback is called when the treeFor response succeeds
*
* @callback PromiseTreeCallbackSuccess
* @param {Node[]} nodes - tree structure of Nodes
*/
/**
* This callback is called when the treeFor response fails
*
* @callback PromiseTreeCallbackError
* @param {string} message - base64 encoded error message
*/
/** Resolves with a {@link PromiseTreeCallbackSuccess}, fails with a {@link PromiseTreeCallbackError}
*
* @typedef {Promise} PromiseTree
*/
/**
* Gets the Tree for a Portfolio
* @param {string} portfolioName Portfolio Name
* @returns {PromiseTree} A promise representing the Portfolio Tree structure
* @example
* smartorg.treeFor(treeID)
* .then(function (tree) {
* console.log(tree);
* })
* .catch(function (err) {
* handleError(err);
* })
*/
treeFor(portfolioName) {
var path_ = this.protocols._getPath('domain/tree');
path_ = `${path_}/${encodeURIComponent(portfolioName)}`;
return this.protocols.apiGet(path_);
}
/** @typedef {object} CategoryConfig
* @property {string} AppliesTo
* @property {boolean} IsMultiSelect
* @property {string} CategoryName - e.g. Region
* @property {array.<string>} CategoryEntries - e.g US, Asia, Europe
*/
/**
* This callback is called when the categoriesConfigFor response succeeds
*
* @callback CategoryConfigPromiseCallbackSuccess
* @param {CategoryConfig[]} categoryConfigs - array of CategoryConfig objectsj
*/
/**
* This callback is called when the categoriesConfigFor response fails
*
* @callback CategoryConfigPromiseCallbackError
* @param {string} message - base64 encoded error message
*/
/** Resolves with a {@link CategoryConfigPromiseCallbackSuccess}, fails with a {@link CategoryConfigPromiseCallbackSuccess}
*
* @typedef {Promise} CategoryConfigPromise
*/
/**
*
*
* @param rootNodeID
* @returns {CategoryConfigPromise}
* @example
* smartorg.categoriesConfigFor(rootNodeID)
* .then(function(categoryConfigs) {
* // categoryConfigs is an array of categoryConfig
* categoryConfigs.forEach(function(categoryConfig) {
* console.log(categoryConfig.AppliesTo);
* console.log(categoryConfig.IsMultiSelect);
* console.log(categoryConfig.CategoryName); //e.g. Region
* console.log(categoryConfig.AutoPropagateUp);
*
* categoryConfig.CategoryEntries.forEach(function(entry) {
* console.log("category entry "+ entry); // e.g. US, Asia, Europe
* });
* });
* })
* .catch(function(err) {
* handleError(err);
* });
*/
categoriesConfigFor(rootNodeID) {
var path_ = this.protocols._getPath('domain/categoryConfig');
path_ = `${path_}/${rootNodeID}`;
return this.protocols.apiGet(path_);
}
/**
* This callback is called when the saveCategoryConfig response succeeds
*
* @callback CategoryConfigSavePromiseCallbackSuccess
* @param {string} statusMessage - status of saveCategoryConfig ( new or existing )
*/
/** Resolves with a {@link CategoryConfigSavePromiseCallbackSuccess}, fails with a {@link CategoryConfigPromiseCallbackSuccess}
*
* @typedef {Promise} CategoryConfigSavePromise
*/
/**
* @param rootNodeID
* @param {CategoryConfig} categoryConfig new or existing category config object ( not string )
* @returns {CategoryConfigSavePromise}
* @example
* smartorg.saveCategoryConfig(rootNodeID, categoryConfig)
* .then(function(statusMessage) {
* console.log(statusMessage);
* })
* .catch(function(err) {
* handleError(err);
* });
*/
saveCategoryConfig(rootNodeID, categoryConfig) {
var path_ = this.protocols._getPath('domain/categoryConfig');
path_ = `${path_}/${rootNodeID}`;
return this.protocols.apiPost(path_, categoryConfig);
}
/**
* Delete a category from config.
*
* @param rootNodeID
* @param categoryName {string} Category name, should be an existing one.
* @returns {*}
* @example
* smartorg.deleteCategoryConfig(rootNodeID, categoryName)
* .then(function(statusMessage) {
* console.log(statusMessage);
* })
* .catch(function(err) {
* handleError(err);
* });
*/
deleteCategoryConfig(rootNodeID, categoryName) {
var path_ = this.protocols._getPath('domain/categoryConfig');
path_ = `${path_}/${rootNodeID}/${encodeURIComponent(categoryName)}`;
return this.protocols.apiDelete(path_);
}
/**
* Get array of tags for a node.
*
* @param nodeID {string}
* @returns {*} Tags promise.
* then: array of tags
* catch: {status: err code, statusText: status text,
* message: err message}
*
* @example
* smartorg.tagsFor(nodeId).then(
* function (result) {
* console.log(result);
* }).catch(function (err) {
* console.log(err);
* });
*/
tagsFor(nodeID) {
var path_ = this.protocols._getPath('domain/tags');
path_ = `${path_}/${nodeID}`;
return this.protocols.apiGet(path_);
}
/**
* This callback is called when the saveTags response succeeds
*
* @callback SaveTagsPromisePromiseCallbackSuccess
* @param {string} statusMessage - status of saveTags
*/
/**
* This callback is called when the saveTags response fails
*
* @callback SaveTagsPromisePromiseCallbackSuccess
* @param {string} statusMessage - error message
*/
/** Resolves with a {@link SaveTagsPromisePromiseCallbackSuccess}, fails with a {@link SaveTagsPromisePromiseCallbackSuccess}
*
* @typedef {Promise} SaveTagsPromise
*/
/**
* @typedef {Array<String>} TagSet
* @example
* //First element in the array is the node ID
* //Second element in the array is a comma delimited string of 1 or more CategoryName:CategoryItemName, all is required
* ["b8652f5d935cf2e22e8e5d01de065d5d","all, Region:Africa, Funded:No, CropType:legumes"]
*/
/**
* Saves array of tags for a node
* @param nodeID
* @param {Array<TagSet>} newTagString
* @returns {SaveTagsPromise}
* @example
* smartorg.saveTags(nodeId, newTagString)
* .then(function(msg) {
*
* console.log(msg);
* })
* .catch(function(err) {
* console.error(err);
* });
*/
saveTags(nodeID, newTagString) {
var path_ = this.protocols._getPath('domain/tags');
path_ = `${path_}/${nodeID}`;
var body_ = JSON.parse(newTagString);
return this.protocols.apiPost(path_, body_);
}
/**
* Save a node's description.
* Both two parameters need to encode in base 64.
*
* @param nodeID {string} Tree node Id.
* @param description {string} Html format description.
*/
saveDescripton(nodeID, description) {
var path_ = this.protocols._getPath('domain/description');
path_ = `${path_}/${nodeID}`;
var body_ = {
'description': description
};
return this.protocols.apiPut(path_, body_);
}
/**
* Save a node's smartText.
* Both two parameters need to encode in base 64.
*
* @param nodeID {string} Tree node Id.
* @param smartText {string} Html format smartText.
*/
saveSmartText(nodeID, smartText) {
var path_ = this.protocols._getPath('domain/smartText');
path_ = `${path_}/${nodeID}`;
var body_ = {
'smartText': smartText
};
return this.protocols.apiPut(path_, body_);
}
/**
* Lookup inputs and outputs that need to go into the universal table
* by key. We need to supply nodeID, and at least one of
* input or output keys (or both).
* @param nodeID {string} Tree node Id.
* @param schema {object} - contains selectedInputKeys {Array},
* selectedOutputKeys {Array} and selectedTableInputKeys {object}
* @param packedReportOptions - contains encoded reportOptions
* @returns list for fields to be displayed in universal output
*/
getFieldList(nodeID, schema, packedReportOptions) {
var path_ = this.protocols._getPath('domain/universal/io/fields');
path_ = `${path_}`;
var body = {
"nodeID": nodeID,
"schema": schema,
"packedReportOptions": packedReportOptions
};
return this.protocols.apiPost(path_, body);
}
/**
* lookup inputs from astro_data and gives the specific fields
* @param templateName
* @param leafOrPlatform
* @param nodeID {string} Tree node Id.
* @returns list for fields to be displayed in universal output
*/
getDisplayNameList(templateName, leafOrPlatform, nodeID) {
var path_ = this.protocols._getPath('domain/universal/io/displayNames');
path_ = `${path_}/${encodeURIComponent(templateName)}/${leafOrPlatform}/${nodeID}`;
return this.protocols.apiGet(path_);
}
/**
* saving univSchema to rootNode
* @param nodeID {string}
* @param schema - has templateName, IOKeys & access
* @param oldName - to check and replace it with new schema name
*/
saveUnivSchemaToRoot(nodeID, schema, oldName) {
var path_ = this.protocols._getPath('domain/universal/io/saveUnivSchemaToRoot');
path_ = `${path_}`;
var body = {
"nodeID": nodeID,
"schema": schema,
"oldName": oldName
};
return this.protocols.apiPost(path_, body);
}
/**
* delete specific schema from rootNode
* @param nodeID {string}
* @param schemaName {string}
*/
deleteUnivSchemaFromRoot(nodeID, schemaName) {
var path_ = this.protocols._getPath('domain/universal/io/deleteUnivSchemaFromRoot');
path_ = `${path_}/${nodeID}/${encodeURIComponent(schemaName)}`;
return this.protocols.apiPut(path_, undefined);
}
/**
* replace univSchema in rootNode
* @param nodeID {string}
* @param schemaName {string}
* @param oldSchemaName {string}
* @param univSchema - schema has templateName, inputKeys, outputKeys & access
*/
replaceUnivSchemaInRoot(nodeID, schemaName, univSchema, oldSchemaName) {
var path_ = this.protocols._getPath('domain/universal/io/replaceUnivSchemaInRoot');
path_ = `${path_}/${nodeID}/${encodeURIComponent(schemaName)}/${encodeURIComponent(oldSchemaName)}`;
return this.protocols.apiPost(path_, univSchema);
}
/**
* save inputs to corresponding nodes
* @param inputs {{}}
*
*/
universalSaveInputs(inputs) {
var path_ = this.protocols._getPath('domain/universal/io/saveInputs');
var body = {
"inputs": inputs
};
return this.protocols.apiPost(path_, body);
}
/**
* Get current api version number.
*
* @returns {*} Api version number promise.
*
* //to do: Fan this is not complete needs @example
* then: string of version number.
* catchL {status: err code, statusText: status text,
* message: err message}
*/
getApiVersionNumber() {
var path_ = this.protocols._getPath('domain/api/version/number');
return this.protocols.apiGetNoAuth(path_);
}
/**
* Get simple outputs from node data
* @returns {*} simple outputs
*
*/
getSimpleOutputs(nodeID) {
var path_ = this.protocols._getPath('domain/output');
path_ = `${path_}/${nodeID}`;
return this.protocols.apiGet(path_);
}
/**
* lookup host specific short code to return url
* @param {string} shortCode - the short code to lookup url
* @returns ShortUrl or 404 Not Found
*/
getInfoForShortURL(shortCode) {
var path_ = this.protocols._getPath('framework/shorturl');
path_ = `${path_}/${shortCode}`;
return this.protocols.apiGet(path_);
}
/**
* @typedef {object} ShortUrl
* @property {string} _id - short url code e.g. JwijDXE
* @property {string} _rev - internal document revision ( ignore )
* @property {string} url - long url
* @property {boolean} byPassLogin
* @property {string} urlLinkName - e.g. Report 2016 PMF submission
* @property {string} csum - checksum of the long url used for duplicate prevention ( ignore )
* @property {array.<string>} CategoryEntries - e.g US, Asia, Europe
*/
/**
* This callback is called when the ShortUrlPromise response succeeds
*
* @callback ShortUrlPromiseeCallbackSuccess
* @param {ShortUrl[]} ShortUrl - a ShortUrl object
*/
/**
* This callback is called when the ShortUrlPromise response fails
*
* @callback ShortUrlPromiseCallbackError
* @param {string} message - base64 encoded error message
*/
/**
* Resolves with a {@link ShortUrlPromiseeCallbackSuccess},
* fails with a {@link ShortUrlPromiseCallbackError}
*
* @typedef {Promise} ShortUrlPromise
*/
/**
*
* @param {string} urlToShorten - long url to shorten
* @param {boolean} byPassLogin - true or false flag to bypass login
* @param {string} urlLinkName - optional link or report name
* @returns ShortUrlPromise
*/
createShortURL(urlToShorten, byPassLogin, urlLinkName) {
var path_ = this.protocols._getPath('framework/shorturl/'); // note the / at the end, this is important to match url for POST
var body_ = {
"ByPassLogin": byPassLogin,
"urlToShorten": encodeURIComponent(urlToShorten),
"urlLinkName": urlLinkName
};
return this.protocols.apiPost(path_, body_);
}
/**
* Generate zendesk authentication url (token) for one login.
*
* @returns {*} Get url promise.
* then: url string.
* catch: error status, text and message.
*
* @example
* smartorg.zendeskAuthUrl().then(
* function (result) {
* console.log(result);
* })
* .catch(function (err) {
* console.err(err);
* });
*/
zendeskAuthUrl(page) {
var path_ = this.protocols._getPath('domain/zenlogin');
path_ = `${path_}/${page}`;
return this.protocols.apiGet(path_);
}
/**
* Generate zendesk authentication url (token) for one login.
* Return to page specified by front end.
*
* If url is not start with "https://smartorg.zendesk.com",
* it will redirect you to that page.
*
* @returns {*} Get url promise.
* then: url string.
* catch: error status, text and message.
*
* @example
* smartorg.zendeskRedirect(returnTo).then(
* function (result) {
* console.log(result);
* })
* .catch(function (err) {
* console.err(err);
* });
*/
zendeskRedirect(returnTo) {
var path_ = this.protocols._getPath('domain/zendesk/redirect');
path_ = `${path_}/${encodeURIComponent(returnTo)}`;
return this.protocols.apiGet(path_);
}
/**
* Get current logged in user profile.
*
* @returns {*} Get user profile promise.
* then: dict of user profile info.
* catch: error status, text and message.
*
* @example
* smartorg.getUserProfile().then(
* function (result) {
* console.log(result);
* })
* .catch(function (err) {
* console.err(err);
* });
*/
getUserProfile() {
var path_ = this.protocols._getPath('domain/user');
return this.protocols.apiGet(path_);
}
/**
* This callback is called when the SaveUserProfilePromise
* response succeeds
*
* @callback SaveUserProfilePromiseCallbackSuccess
* @param {string} message - plaintext message
*/
/**
* This callback is called when the SaveUserProfilePromise
* response fails
*
* @callback SaveUserProfilePromiseCallbackError
* @param {string} message - plaintext message
*/
/**
* Resolves with a {@link SaveUserProfilePromiseCallbackSuccess},
* fails with a {@link SaveUserProfilePromiseCallbackError}
*
* @typedef {Promise} SaveUserProfilePromise
*/
/**
* Save (update) user profile information. This one is for user
* to change their own profiles.
*
* @param username {string} Username as login name.
* @param name {string} User full name in "Lastname, Firstname"
* @param email {string}
* @param phone1 {string} Phone number, only + and numbers.
* @param organisation {string}
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
saveUserProfile(username, name, email, phone1, organisation) {
var path_ = this.protocols._getPath('domain/user');
var body_ = {
'username': username,
'name': name,
'phone1': phone1,
'email': email,
'organisation': organisation
};
return this.protocols.apiPut(path_, body_);
}
/**
* This callback is called when the UserProfileByIdPromise
* response succeeds
*
* @callback UserProfileByIdPromiseCallbackSuccess
* @param {object} userInfo - A user object with all property
* except password
*/
/**
* This callback is called when the UserProfileByIdPromise
* response fails
*
* @callback UserProfileByIdPromiseCallbackError
* @param {string} message - plaintext message
*/
/**
* Resolves with a {@link UserProfileByIdPromiseCallbackSuccess},
* fails with a {@link UserProfileByIdPromiseCallbackError}
*
* @typedef {Promise} UserProfileByIdPromise
*/
/**
* Read user profile by his id.
*
* @param userId {string} Unique user database id.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
getUserProfileByID(userId) {
var path_ = this.protocols._getPath('framework/user');
path_ = `${path_}/${userId}`;
return this.protocols.apiGet(path_);
}
/**
* This callback is called when the NewUserPromise
* response succeeds
*
* @callback NewUserPromiseCallbackSuccess
* @param {string} message - plaintext message
*/
/**
* This callback is called when the NewUserPromise
* response fails
*
* @callback NewUserPromiseCallbackError
* @param {string} message - plaintext message
*/
/**
* Resolves with a {@link NewUserPromiseCallbackSuccess},
* fails with a {@link NewUserPromiseCallbackError}
*
* @typedef {Promise} NewUserPromise
*/
/**
* Creates a new user
* @param username {string} Unique username. Server will double
* check if it is unique.
* @param name {string} Full name of user in format "Last, First".
* @param password {string} Password in plain text. x_x
* @param email {string}
* @param phone1 {string} In format +14081231234.
* @param organisation {string}
* @param defaultGroupName {string} Group name instead of id.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
newUser(username, name, password, email, phone1, organisation, defaultGroupName) {
//debugger;
var path_ = this.protocols._getPath('framework/user');
var body_ = {
'username': username,
'name': name,
'password': password,
'phone1': phone1,
'email': email,
'organisation': organisation,
'defaultGroup': defaultGroupName
};
return this.protocols.apiPost(path_, body_);
}
/**
* This callback is called when the ModifyUserPromise
* response succeeds
*
* @callback ModifyUserPromiseCallbackSuccess
* @param {string} message - plaintext message
*/
/**
* This callback is called when the ModifyUserPromise
* response fails
*
* @callback ModifyUserPromiseCallbackError
* @param {string} message - plaintext message
*/
/**
* Resolves with a {@link ModifyUserPromiseCallbackSuccess},
* fails with a {@link ModifyUserPromiseCallbackError}
*
* @typedef {Promise} ModifyUserPromise
*/
/**
* Similar to save user profile. This one is for address book use.
*
* @param userID {string} Unique user database id.
* @param username {string} Unique username. Server will double
* check if it is unique.
* @param name {string} Full name of user in format "Last, First".
* @param email {string}
* @param phone1 {string} In format +14081231234.
* @param organisation {string}
* @param defaultGroupName {string} Group name instead of id.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
modifyExistingUser(userID, username, name, email, phone1, organisation, defaultGroupName) {
var path_ = this.protocols._getPath('framework/user');
var body_ = {
'userID': userID,
'username': username,
'name': name,
'phone1': phone1,
'email': email,
'organisation': organisation,
'defaultGroup': defaultGroupName
};
return this.protocols.apiPut(path_, body_);
}
/**
* Update user admin settings, including force user to change
* password on login and reset user to first login status.
*
* @param userId {string} Unique user id (couch db doc id).
* @param adminSettings {object} A dict contains everything needs
* to be set. For now it has passwordChange and
* resetToFirstLogin. Anything come in later just add to the
* dict object.
*
* @returns {*|Promise.<T>|Promise|axios.Promise}
* Result status promise.
* then: status 0, no data.
* catch: status not 0, exception object or message array.
*/
updateUserAdminSettings(userId, adminSettings) {
var path_ = this.protocols._getPath('framework/user/settings');
var body_ = {
'userID': userId,
'passwordChange': adminSettings['passwordChange'],
'resetToFirstLogin': adminSettings['resetToFirstLogin']
};
return this.protocols.apiPut(path_, body_);
}
/**
* This callback is called when the ListUserPromise
* response succeeds
*
* @callback ListUserPromiseCallbackSuccess
* @param {Array<object>} userlist - List of user objects.
*/
/**
* This callback is called when the ListUserPromise
* response fails
*
* @callback ListUserPromiseCallbackError
* @param {string} message - plaintext message
*/
/**
* Resolves with a {@link ListUserPromiseCallbackSuccess},
* fails with a {@link ListUserPromiseCallbackError}
*
* @typedef {Promise} ListUserPromise
*/
/**
* Get list of all user with all info except password.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
getListOfUsers() {
var path_ = this.protocols._getPath('framework/user');
return this.protocols.apiGet(path_);
}
/**
* This callback is called when the DeleteUserPromise
* response succeeds
*
* @callback DeleteUserPromiseCallbackSuccess
* @param {string} message - plaintext message
*/
/**
* This callback is called when the DeleteUserPromise
* response fails
*
* @callback DeleteUserPromiseCallbackError
* @param {string} message - plaintext message
*/
/**
* Resolves with a {@link DeleteUserPromiseCallbackSuccess},
* fails with a {@link DeleteUserPromiseCallbackError}
*
* @typedef {Promise} DeleteUserPromise
*/
/**
* Delete a user from database by his id.
*
* @param userId {string} User unique id.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
deleteUser(userId) {
var path_ = this.protocols._getPath('framework/user');
path_ = `${path_}/${userId}`;
return this.protocols.apiDelete(path_);
}
/**
* Call this api to change the password for user.
*
* @param oldpassword {string} - users: pass in clear text old
* password. admin use: pass in clear text string *optional*
* for admin reset ( must be called by user in administrators
* group )
* @param newpassword {string} - clear text new user password
* @returns {string} - status message of modifying password
* A promise.
* then: dict of result, status 0 as success, message as
* array of strings of messages.
* catch: error status, text and message.
*/
resetPassword(oldpassword, newpassword) {
var path_ = this.protocols._getPath('framework/password');
var body_ = {
'oldpassword': oldpassword,
'newpassword': newpassword
};
return this.protocols.apiPut(path_, body_);
}
/**
* Call this api to change password to current logged in user.
* Special version for first time login and reset password.
*
* TODO: Fix this security glitch!
*
* @param newpassword {string} Clear text new user password
* @returns {*|Promise.<T>|Promise|axios.Promise}
* A promise.
* then: dict of result, status 0 as success, message as
* array of strings of messages.
* catch: error status, text and message.
*/
changePasswordWithoutOld(newpassword) {
var path_ = this.protocols._getPath('framework/password');
var body_ = {
'newpassword': newpassword
};
return this.protocols.apiPost(path_, body_);
}
/**
* Admin users call this function to set other user's password.
* Server will check if the user calling this function is admin.
*
* @param username {string} This function use username instead of
* user id. Username should also be unique.
* @param password {string} Plain text new user password
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
adminSetPassword(username, password) {
var path_ = this.protocols._getPath('framework/password/admin');
var body_ = {
'username': username,
'newpassword': password
};
return this.protocols.apiPost(path_, body_);
}
/**
* Get a list of all groups with name, id, and list of users of
* groups.
*
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
getListOfGroups() {
var path_ = this.protocols._getPath('framework/group');
return this.protocols.apiGet(path_);
}
/**
* Create a new group.
*
* @param groupName {string} Group name, should be unique.
* @param description {string} Description of the group.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
createNewGroup(groupName, description) {
var path_ = this.protocols._getPath('framework/group');
var body_ = {
'groupName': groupName,
'groupDescription': description
};
return this.protocols.apiPost(path_, body_);
}
/**
* Edit a group info. Only group description can be change.
*
* @param groupId {string} Unique database id for group.
* @param groupName {string} Unique group name.
* @param description {string}
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
editGroup(groupId, groupName, description) {
// Group name should be able to change but now we are
// using group name as id in some place, so we must keep it
// unchanged.
var path_ = this.protocols._getPath('framework/group');
path_ = `${path_}/${groupId}`;
var body_ = {
'groupName': groupName,
'groupDescription': description
};
return this.protocols.apiPut(path_, body_);
}
/**
* Delete a group from database.
*
* @param groupId {string} Unique database id for group.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
deleteGroup(groupId) {
// Chosen group will remain there. Need to fix sometime.
var path_ = this.protocols._getPath('framework/group');
path_ = `${path_}/${groupId}`;
return this.protocols.apiDelete(path_);
}
/**
* Add a user to a group.
*
* @param groupId {string} Group to add a user to.
* @param userId {string} Add this user to group.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
groupAddUser(groupId, userId) {
var path_ = this.protocols._getPath('framework/usergroup');
path_ = `${path_}/${groupId}/${userId}`;
return this.protocols.apiPost(path_, {});
}
/**
* Remove a user from a group.
*
* @param groupId {string} Group to remove user.
* @param userId {string} This user will be removed from given
* group.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
groupRemoveUser(groupId, userId) {
var path_ = this.protocols._getPath('framework/usergroup');
path_ = `${path_}/${groupId}/${userId}`;
return this.protocols.apiDelete(path_);
}
/**
* Update user email address. Will be obselete soon.
*
* @param email {string} Email address.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
updateUserEmail(email) {
var path_ = this.protocols._getPath('domain/user/email');
path_ = `${path_}/${email}`;
var body_ = {};
return this.protocols.apiPost(path_, body_);
}
/**
* Confirm email address by username and key. At this point user
* should not be logged in, so this call will bypass authentication
* and use username.
*
* @param username {string} Username, should be unique.
* @param key {string} System generated one time key.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
confirmUserEmail(username, key) {
// Maybe user id is a better idea.
var path_ = this.protocols._getPath('domain/user/email');
path_ = `${path_}/${username}/confirm/${key}`;
return this.protocols.apiPostNoAuth(path_, {});
}
/**
* @param treeID {string} - The treeID for which category
* assignment is sought
* @returns {object} - Category assignment object
*/
getAssignCategory(treeID) {
var path_ = this.protocols._getPath('domain/getAssignCategory');
path_ = `${path_}/${encodeURIComponent(treeID)}`;
return this.protocols.apiGet(path_);
}
/**
* Get template restriction by tree id.
*
* @param treeId {string} Root node name as tree id.
*
* @returns {*|Promise.<T>|Promise|axios.Promise} Resolved will
* be a list of chosen template names and a list of unchosen.
*/
getTemplateRestrictions(treeId) {
var path_ = this.protocols._getPath('domain/restrict/template');
path_ = `${path_}/${encodeURIComponent(treeId)}`;
return this.protocols.apiGet(path_);
}
/**
* Set template restriction.
*
* @param treeId {string} Root node name as tree id.
* @param chosenTemplates {Array<string>} Array of chosen template
* names. We do not save unchosen ones.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
setTemplateRestrictions(treeId, chosenTemplates) {
var path_ = this.protocols._getPath('domain/restrict/template');
path_ = `${path_}/${encodeURIComponent(treeId)}`;
var body_ = {'chosen': chosenTemplates};
return this.protocols.apiPut(path_, body_);
}
/**
* Get group restrictions. Same thing as templates.
*
* @param treeId {string} Root node name as tree id.
* @returns {*|Promise.<T>|Promise|axios.Promise} Two arrays of
* chosen and unchosen.
*/
getGroupRestrictions(treeId) {
var path_ = this.protocols._getPath('domain/restrict/group');
path_ = `${path_}/${encodeURIComponent(treeId)}`;
return this.protocols.apiGet(path_);
}
/**
* Set group restrictions.
*
* @param treeId {string} Root node name as tree id.
* @param chosenGroups {Array<string>} Array of chosen group
* names. We do not save unchosen ones.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
setGroupRestrictions(treeId, chosenGroups) {
// Deleted groups will still be in this list. Need to fix.
var path_ = this.protocols._getPath('domain/restrict/group');
path_ = `${path_}/${encodeURIComponent(treeId)}`;
var body_ = {'chosen': chosenGroups};
return this.protocols.apiPut(path_, body_);
}
/**
* Set group restrictions and template restrictions at the same
* time.
*
* @param treeId {string} Root node name as tree id.
* @param groups {Array<string>} Array of chosen group names.
* @param templates {Array<string>} Array of chosen template
* names.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
setGroupsAndTemplatesRestrictions(treeId, groups, templates) {
var path_ = this.protocols._getPath('domain/restrict/both');
path_ = `${path_}/${encodeURIComponent(treeId)}`;
var body_ = {
'groups': groups,
'templates': templates
};
return this.protocols.apiPut(path_, body_);
}
/**
* Get access control list through tree id.
*
* @param treeId {string} Root node name as tree id.
* @returns {*|Promise.<T>|Promise|axios.Promise} Resolved will
* get a acl object with owner and acl groups.
*/
getAcl(treeId) {
var path_ = this.protocols._getPath('domain/acl');
path_ = `${path_}/${encodeURIComponent(treeId)}`;
return this.protocols.apiGet(path_);
}
/**
* Set acl info.
*
* @param treeId {string} Root node name as tree id.
* @param acl {object} Though we request acl object here, we only
* save group info into database.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
setAcl(treeId, acl) {
var path_ = this.protocols._getPath('domain/acl');
path_ = `${path_}/${encodeURIComponent(treeId)}`;
var body_ = {
'acl': acl
};
return this.protocols.apiPut(path_, body_);
}
/**
* Get welcome message, including license and security warning.
*
* @param messageType {string} Can be LICENSE and SECURITY_WARNING.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
getWelcomeMessage(messageType) {
var path_ = this.protocols._getPath('domain/welcome/message');
path_ = `${path_}/${messageType}`;
return this.protocols.apiGet(path_);
}
/**
* Set welcome message. This function will push whatever string
* passed in without doing any encoding. So encode the message
* before calling this.
*
* @param messageType {string} Can be LICENSE and SECURITY_WARNING.
* @param message {string} Message to be save into database.
* @param state {boolean} True for always display.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
setWelcomeMessage(messageType, message, state) {
var path_ = this.protocols._getPath('domain/welcome/message');
path_ = `${path_}/${messageType}`;
var body_ = {
'message': message,
'state': state
};
return this.protocols.apiPut(path_, body_);
}
/**
* Accept license or security warnings.
*
* @param messageType {string} Can be LICENSE and SECURITY_WARNING.
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
acceptWelcomeMessage(messageType) {
var path_ = this.protocols._getPath('domain/welcome/accept');
path_ = `${path_}/${messageType}`;
return this.protocols.apiPut(path_, {});
}
/**
* Fetch input data in a excel format string.
*
* @param treeID {string} Tree id, ie. root node name.
* @param nodeID {string} Node id, can be any node. Will download
* input of a subtree from this node.
*
* @return {*|Promise.<T>|Promise|axios.Promise}
* Download input promise.
* then:
* catch:
*/
fetchInputData(treeID, nodeID) {
var path_ = this.protocols._getPath('domain/download/input');
path_ = `${path_}/${encodeURIComponent(treeID)}/${nodeID}`;
return this.protocols.apiGet(path_);
}
/**
* Request reset password.
* @param username {string}
* @param email {string}
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
requestResetPassword(username, email) {
var path_ = this.protocols._getPath('framework/password/request');
path_ = `${path_}/${username}/${email}`;
return this.protocols.apiGetNoAuth(path_);
}
/**
* Check if the username and key matches and not expired.
*
* @param username {string}
* @param key {string}
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
checkResetPasswordKey(username, key) {
var path_ = this.protocols._getPath('framework/password/reset');
path_ = `${path_}/${username}/${key}`;
return this.protocols.apiGetNoAuth(path_);
}
/**
* Reset password to new password. Will check the username and
* key again to make sure everything is correct.
*
* @param username {string}
* @param key {string}
* @param newPassword {string}
* @returns {*|Promise.<T>|Promise|axios.Promise}
*/
resetPasswordThroughEmail(username, key, newPassword) {
var path_ = this.protocols._getPath('framework/password/reset');
path_ = `${path_}/${username}/${key}`;
var body_ = {
newpass: newPassword
};
return this.protocols.apiPostNoAuth(path_, body_);
}
/**
* Downloads spreadsheet model applicable at node with given nodeID.
* Data is a json object with the following structure:
* @example
* smartorg.downloadSpreadsheet(myNodeID).then(function(answer) {
* console.log(answer.templateName); // e.g. simpleLaunch
* console.log(answer.extension); // e.g. xls
* console.log(answer.modelData); // Base-64 encoded binary data
* }).catch(function(err) {
* console.log(err);
* });
* @param nodeID
* @return {*|Promise|axios.Promise}
*/
downloadSpreadsheet(nodeID) {
var path_ = this.protocols._getPath('domain/downloadTemplate');
path_ = `${path_}/${nodeID}`;
var body_ = {};
return this.protocols.apiPostNoAuth(path_, body_);
}
}
export default SmartOrg;
// module.exports = SmartOrg;
//For users not using a module loading eg(browersify), need a way
// to expose it to them via the window object
if (typeof window != 'undefined') {
window.SmartOrg = SmartOrg;
}
//[NOTES]
//
// [1] - Promises - alt way to bubble promise up to next catch statement ...
// throw new APIErr({'status':error.status,'statusText':error.statusText,'message':error.data.message})
//
// [2] - Symbols - a neat way to set ACL/scope on methods etc ...
// export const createHMACget = Symbol('createHMACget');
// is possible to use reflection but hides this sufficiently for now ...
// also if you wanted to extend SmartOrg ... avoids name collisions
//
// [3] - Symbols - Private Fxn in action
// symbols way to define unique primatives and give controll over access to properties and avoid collisions
// prototype instances named props on fxns
// this is a way to hide -
/*
var rangal = new Rangal("server.smartorg.com");
rangal.login(username,password, function(loginStatus) {});
rangal.treeFor("Product Launch", function(treeJSON) {});
rangal.actionByDisplayName("Product Launch", "Breath Strips Node ID", "Tornado Action ID", function(tornadoJSON) {});
rangal.portfolios(function(portfolioJSON) {});
rangal.actionMenuFor("Product Launch", "Breath Strips", function(actionMenuJSON){});
*/