/**
* @copyright 2015 Tridium, Inc. All Rights Reserved.
* @author Logan Byam
*/
/**
* @module bajaux/dragdrop/NavNodeEnvelope
*/
define([ 'baja!',
'baja!baja:INavNode',
'jquery',
'Promise',
'underscore',
'bajaux/dragdrop/Envelope',
'nmodule/js/rc/asyncUtils/asyncUtils' ], function (
baja,
types,
$,
Promise,
_,
Envelope,
asyncUtils) {
'use strict';
var doRequire = asyncUtils.doRequire;
var getNavNode = _.once(function () {
return doRequire('bajaScript/baja/nav/NavNode');
});
////////////////////////////////////////////////////////////////
// Support functions
////////////////////////////////////////////////////////////////
function getTypeSpecs(obj) {
var kids = obj.kids || [],
kidSpecs = kids.map(getTypeSpecs);
return [ obj.typeSpec ].concat(kidSpecs);
}
/**
* Extract an array of all type specs from the array of JSON objects.
*
* @inner
* @param {Array.<Object>} json
* @returns {Array.<String>}
*/
function getAllTypeSpecs(json) {
return _.uniq(_.flatten(json.map(getTypeSpecs)));
}
function toJson(navNode) {
var kids = navNode.getSlots &&
navNode.getSlots().is('baja:INavNode').toValueArray(),
ord = navNode.getNavOrd();
return {
ord: ord && String(ord),
name: navNode.getNavName(),
displayName: navNode.getNavDisplayName(),
icon: navNode.getNavIcon().encodeToString(),
description: navNode.getNavDescription(),
typeSpec: navNode.getNavTypeSpec(),
kids: kids ? kids.map(toJson) : []
};
}
function toNavNode(obj) {
var typeSpec = obj.typeSpec,
type = baja.lt(obj.typeSpec);
if (!type || !type.is('baja:INavNode')) {
throw new Error('only INavNodes supported, ' + typeSpec + ' found');
}
return Promise.all([
getNavNode(),
Promise.all((obj.kids || []).map(toNavNode))
])
.then(([ NavNode, kids ]) => {
const navNode = new NavNode({
navName: obj.name,
displayName: obj.displayName,
description: obj.description,
ord: String(obj.ord),
icon: obj.icon,
typeSpec
});
kids.forEach((kid) => { kid.getNavParent = () => navNode; });
navNode.getType = () => type;
navNode.getNavChildren = () => Promise.resolve(kids);
return navNode;
});
}
////////////////////////////////////////////////////////////////
// NavNodeEnvelope
////////////////////////////////////////////////////////////////
/**
* Envelope for transforming raw JSON into NavNode instances, or vice versa.
*
* @class
* @extends module:bajaux/dragdrop/Envelope
* @alias module:bajaux/dragdrop/NavNodeEnvelope
* @param {Array.<Object>|Array.<baja.NavNode>} arr either an array of raw
* JSON to be converted to NavNodes, or an array of NavNodes to be converted
* to JSON
* @throws {Error} if a non-Array given
*/
var NavNodeEnvelope = function NavNodeEnvelope(arr) {
Envelope.apply(this, arguments);
if (!Array.isArray(arr)) {
throw new Error('array required');
}
var navNodes,
json;
//TODO: need an "isArrayOf" or similar
if (baja.hasType(arr[0], 'baja:INavNode')) {
navNodes = arr;
} else {
json = arr;
}
this.$navNodes = navNodes;
this.$json = json;
};
NavNodeEnvelope.prototype = Object.create(Envelope.prototype);
NavNodeEnvelope.prototype.constructor = NavNodeEnvelope;
/**
* @returns {string} `niagara/navnodes`
*/
NavNodeEnvelope.prototype.getMimeType = function () {
return 'niagara/navnodes';
};
/**
* Get the JSON representations of the envelope's NavNodes:
*
* [{
* "name": "navName",
* "displayName": "navDisplayName",
* "description": "navDescription",
* "icon": "navIcon",
* "ord": "navOrd",
* "typeSpec": "typeSpec",
* "kids": [ \/* child nav node JSON objects *\/ ]
* }]
*
* @returns {Promise.<Array.<object>>} promise to be resolved with an array of raw
* JSON objects
*/
NavNodeEnvelope.prototype.toJson = function () {
return Promise.resolve(
this.$json || (this.$json = this.$navNodes.map(toJson))
);
};
/**
* Get the actual NavNodes represented by this envelope.
*
* @returns {Promise.<Array.<baja.NavNode>>} promise to be resolved with an array of
* NavNode instances
*/
NavNodeEnvelope.prototype.toValues = function () {
var that = this,
json = that.$json,
navNodes = that.$navNodes;
if (navNodes) {
return Promise.resolve(navNodes);
}
return baja.importTypes(getAllTypeSpecs(json))
.then(function () {
return Promise.all(_.map(json, toNavNode));
})
.then(function (navNodes) {
return (that.$navNodes = navNodes);
});
};
return NavNodeEnvelope;
});