<commit_before>/*globals define, WebGMEGlobal*/
/*jshint browser: true*/

/**
 * @author rkereskenyi / https://github.com/rkereskenyi
 */

define(['js/logger',
    'js/Constants',
    'js/Utils/GMEConcepts',
    'js/NodePropertyNames',
    'js/RegistryKeys',
    'js/Utils/PreferencesHelper'
], function (Logger,
             CONSTANTS,
             GMEConcepts,
             nodePropertyNames,
             REGISTRY_KEYS,
             PreferencesHelper) {
    'use strict';

    var PartBrowserControl,
        WIDGET_NAME = 'PartBrowser',
        DEFAULT_DECORATOR = 'ModelDecorator';

    PartBrowserControl = function (myClient, myPartBrowserView) {
        var self = this;

        this._client = myClient;
        this._partBrowserView = myPartBrowserView;

        //the ID of the node whose valid children types should be displayed
        this._containerNodeId = WebGMEGlobal.State.getActiveObject() || null;

        //decorators can use it to ask for notifications about their registered sub IDs
        this._componentIDPartIDMap = {};

        //stores the last known active aspect so that we can decide if it is reall
        this._aspect = null;

        //stores the GUID of the UI piece which is the identification of the client communications
        this._guid = '_part_browser_';

        //collects information for all the part descriptors
        this._descriptorCollection = {};

        //the decorator instances of the parts
        this._partInstances = {};

        //the territory rules
        this._territoryRules = {'': {children: 0}};

        //the current visualizer
        this._visualizer = null;

        this._initDragDropFeatures();

        this._logger = Logger.create('gme:Panels:PartBrowser:PartBrowserPanelControl',
            WebGMEGlobal.gmeConfig.client.log);
        this._logger.debug('Created');

        WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, function (model, activeObject) {
            self._containerNodeId = activeObject;
            self._updateDescriptor(self._getPartDescriptorCollection());
        });

        WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_TAB, function (/*model, activeTabId*/) {
            var activeAspect = WebGMEGlobal.State.getActiveAspect();
            activeAspect = activeAspect === CONSTANTS.ASPECT_ALL ? null : activeAspect;
            if (self._aspect !== activeAspect) {
                self._aspect = activeAspect;
                self._updateDescriptor(self._getPartDescriptorCollection());
            }
            //else {
            //    if (self._visualizer === 'SetEditor') {
            //        //we have to react to all tab change...
            //        self._updateDescriptor(self._getPartDescriptorCollection());
            //    }
            //} //TODO right now we cannot create objects in setEditor so we do not need this functionality
        });

        WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_VISUALIZER, function (model, activeVisualizer) {
            if (self._visualizer !== activeVisualizer) {
                self._visualizer = activeVisualizer;
                self._updateDescriptor(self._getPartDescriptorCollection());
            }
        });

        this._nodeEventHandling = function (events) {
            var metaChange = false,
                metaNodes = self._client.getAllMetaNodes() || [],
                metaPaths = [],
                i;

            for (i = 0; i < metaNodes.length; i += 1) {
                metaPaths.push(metaNodes[i].getId());
            }
            metaPaths.push(CONSTANTS.PROJECT_ROOT_ID);

            for (i = 0; i < events.length; i += 1) {
                if (metaPaths.indexOf(events[i].eid) !== -1) {
                    metaChange = true;
                    break;
                }
            }

            if (metaChange) {
                self._updateDescriptor(self._getPartDescriptorCollection());
            } else {
                self._updateDecorators();
            }

        };

        this._client.addUI(self, self._nodeEventHandling, this._guid);
        this._client.updateTerritory(this._guid, this._territoryRules);
    };

    PartBrowserControl.prototype._updateDescriptor = function (newDescriptor) {
        var keys = Object.keys(newDescriptor || {}).sort(),
            i,
            self = this,
            div,
            newTerritoryRules;

        //add and update
        for (i = 0; i < keys.length; i += 1) {
            if (!this._descriptorCollection[keys[i]]) {
                //new item
                this._partInstances[keys[i]] = this._partBrowserView.addPart(keys[i], newDescriptor[keys[i]]);
            } else if (this._descriptorCollection[keys[i]].decorator !== newDescriptor[keys[i]].decorator) {
                this._partInstances[keys[i]] = this._partBrowserView.updatePart(keys[i], newDescriptor[keys[i]]);
            }

            if (!this._descriptorCollection[keys[i]] ||
                (this._descriptorCollection[keys[i]].visibility !== newDescriptor[keys[i]].visibility)) {
                div = this._partBrowserView._getPartDiv(keys[i]);
                if (newDescriptor[keys[i]].visibility === 'hidden') {
                    div.hide();
                } else if (newDescriptor[keys[i]].visibility === 'visible') {
                    div.show();
                    this._partBrowserView.setEnabled(keys[i], true);
                } else {
                    div.show();
                    this._partBrowserView.setEnabled(keys[i], false);
                }
            }
        }

        //remove
        keys = Object.keys(this._descriptorCollection);

        for (i = 0; i < keys.length; i += 1) {
            if (!newDescriptor[keys[i]]) {
                this._partBrowserView.removePart(keys[i]);
                delete this._partInstances[keys[i]];
            }
        }

        this._descriptorCollection = newDescriptor;
        newTerritoryRules = this._getTerritoryPatterns();
        if (JSON.stringify(this._territoryRules) !== JSON.stringify(newTerritoryRules)) {
            this._territoryRules = newTerritoryRules;
            setTimeout(function () {
                self._client.updateTerritory(self._guid, self._territoryRules);
            }, 0);
        } else {
            this._updateDecorators();
        }
    };

    PartBrowserControl.prototype._getPartDescriptorCollection = function () {
        var containerNode = this._client.getNode(this._containerNodeId),
            metaNodes = this._client.getAllMetaNodes(),
            descriptorCollection = {},
            descriptor,
            validInfo,
            keys,
            i;
        //getSetName = function () {
        //    var setNamesOrdered = (containerNode.getSetNames() || []).sort(),
        //        tabId = WebGMEGlobal.State.getActiveTab();
        //
        //    if (tabId < setNamesOrdered.length) {
        //        return setNamesOrdered[tabId];
        //    }
        //
        //    return null;
        //}; not used yet

        for (i = 0; i < metaNodes.length; i += 1) {
            descriptor = this._getPartDescriptor(metaNodes[i].getId());
            if (descriptor) {
                descriptorCollection[metaNodes[i].getId()] = this._getPartDescriptor(metaNodes[i].getId());
                descriptorCollection[metaNodes[i].getId()].visibility = 'hidden';
            }
        }

        if (containerNode) {
            if (this._visualizer === 'GraphViz') {
                //do nothing as partBrowser should not have any element in GraphViz
                validInfo = {};
            } else if (this._visualizer === 'SetEditor') {
                //i = getSetName();
                //if (i) {
                //    validInfo = containerNode.getValidSetMemberTypesDetailed(i);
                //} else {
                //    validInfo = {};
                //} //TODO now we cannot create elements in set editor
                validInfo = {};
            } else if (this._visualizer === 'METAAspect') {
                //here we should override the container node to the META container node - ROOT as of now
                containerNode = this._client.getNode(CONSTANTS.PROJECT_ROOT_ID);
                validInfo = containerNode.getValidChildrenTypesDetailed(null, true);
            } else {
                //default is the containment based elements
                validInfo = containerNode.getValidChildrenTypesDetailed(this._aspect);
            }

            keys = Object.keys(validInfo);

            for (i = 0; i < keys.length; i += 1) {
                if (validInfo[keys[i]]) {
                    descriptorCollection[keys[i]].visibility = 'visible';
                } else {
                    descriptorCollection[keys[i]].visibility = 'grayed';
                }
            }
        }

        return descriptorCollection;
    };

    PartBrowserControl.prototype._getTerritoryPatterns = function () {
        var patterns = {'': {children: 0}},
            keys,
            query,
            i;

        if (this._containerNodeId) {
            patterns[this._containerNodeId] = {children: 0};

            keys = Object.keys(this._partInstances || {}).sort();
            for (i = 0; i < keys.length; i += 1) {
                if (this._partInstances[keys[i]]) {
                    //console.log(this._partInstances[keys[i]].getTerritoryQuery());
                    query = this._partInstances[keys[i]].getTerritoryQuery() || {};

                    if (query[keys[i]]) {
                        patterns[keys[i]] = query[keys[i]];
                    }
                }
            }
        }

        return patterns;
    };

    PartBrowserControl.prototype._getObjectDescriptor = function (nodeId) {
        var nodeObj = this._client.getNode(nodeId),
            objDescriptor;

        if (nodeObj) {
            objDescriptor = {};

            objDescriptor.id = nodeObj.getId();
            objDescriptor.decorator = nodeObj.getRegistry(REGISTRY_KEYS.DECORATOR) || DEFAULT_DECORATOR;
            objDescriptor.name = nodeObj.getAttribute(nodePropertyNames.Attributes.name);
        } else {
            this._logger.error('Node not loaded', nodeId);
        }

        return objDescriptor;
    };

    PartBrowserControl.prototype._getItemDecorator = function (decorator) {
        var result;

        result = this._client.decoratorManager.getDecoratorForWidget(decorator, WIDGET_NAME);
        if (!result) {
            result = this._client.decoratorManager.getDecoratorForWidget(DEFAULT_DECORATOR, WIDGET_NAME);
        }

        return result;
    };

    PartBrowserControl.prototype._getPartDescriptor = function (id) {
        var desc = this._getObjectDescriptor(id);

        if (desc) {
            desc.decoratorClass = this._getItemDecorator(desc.decorator);
            desc.control = this;
            desc.metaInfo = {};
            desc.metaInfo[CONSTANTS.GME_ID] = id;
            desc.preferencesHelper = PreferencesHelper.getPreferences();
            desc.aspect = this._aspect;
        }

        return desc;
    };

    PartBrowserControl.prototype.registerComponentIDForPartID = function (componentID, partId) {
        this._componentIDPartIDMap[componentID] = this._componentIDPartIDMap[componentID] || [];
        if (this._componentIDPartIDMap[componentID].indexOf(partId) === -1) {
            this._componentIDPartIDMap[componentID].push(partId);
        }
    };

    PartBrowserControl.prototype.unregisterComponentIDFromPartID = function (componentID, partId) {
        var idx;

        if (this._componentIDPartIDMap && this._componentIDPartIDMap[componentID]) {
            idx = this._componentIDPartIDMap[componentID].indexOf(partId);
            if (idx !== -1) {
                this._componentIDPartIDMap[componentID].splice(idx, 1);

                if (this._componentIDPartIDMap[componentID].length === 0) {
                    delete this._componentIDPartIDMap[componentID];
                }
            }
        }
    };

    PartBrowserControl.prototype._initDragDropFeatures = function () {
        var dragEffects = this._partBrowserView.DRAG_EFFECTS;

        this._partBrowserView.getDragEffects = function (/*el*/) {
            return [dragEffects.DRAG_CREATE_INSTANCE];
        };

        this._partBrowserView.getDragItems = function (el) {
            return [el.attr('id')];
        };
    };

    PartBrowserControl.prototype._updateDecorators = function () {
        var i,
            keys = Object.keys(this._partInstances || {});

        for (i = 0; i < keys.length; i += 1) {
            if (this._descriptorCollection[keys[i]] && this._descriptorCollection[keys[i]].visibility !== 'hidden') {
                this._partInstances[keys[i]].update();
            }
        }
    };

    return PartBrowserControl;
});<commit_msg>Sort part browser alphabetically, then based on relids.<commit_after>/*globals define, WebGMEGlobal*/
/*jshint browser: true*/

/**
 * @author rkereskenyi / https://github.com/rkereskenyi
 */

define(['js/logger',
    'js/Constants',
    'js/Utils/GMEConcepts',
    'js/NodePropertyNames',
    'js/RegistryKeys',
    'js/Utils/PreferencesHelper'
], function (Logger,
             CONSTANTS,
             GMEConcepts,
             nodePropertyNames,
             REGISTRY_KEYS,
             PreferencesHelper) {
    'use strict';

    var PartBrowserControl,
        WIDGET_NAME = 'PartBrowser',
        DEFAULT_DECORATOR = 'ModelDecorator';

    PartBrowserControl = function (myClient, myPartBrowserView) {
        var self = this;

        this._client = myClient;
        this._partBrowserView = myPartBrowserView;

        //the ID of the node whose valid children types should be displayed
        this._containerNodeId = WebGMEGlobal.State.getActiveObject() || null;

        //decorators can use it to ask for notifications about their registered sub IDs
        this._componentIDPartIDMap = {};

        //stores the last known active aspect so that we can decide if it is reall
        this._aspect = null;

        //stores the GUID of the UI piece which is the identification of the client communications
        this._guid = '_part_browser_';

        //collects information for all the part descriptors
        this._descriptorCollection = {};

        //the decorator instances of the parts
        this._partInstances = {};

        //the territory rules
        this._territoryRules = {'': {children: 0}};

        //the current visualizer
        this._visualizer = null;

        this._initDragDropFeatures();

        this._logger = Logger.create('gme:Panels:PartBrowser:PartBrowserPanelControl',
            WebGMEGlobal.gmeConfig.client.log);
        this._logger.debug('Created');

        WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, function (model, activeObject) {
            self._containerNodeId = activeObject;
            self._updateDescriptor(self._getPartDescriptorCollection());
        });

        WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_TAB, function (/*model, activeTabId*/) {
            var activeAspect = WebGMEGlobal.State.getActiveAspect();
            activeAspect = activeAspect === CONSTANTS.ASPECT_ALL ? null : activeAspect;
            if (self._aspect !== activeAspect) {
                self._aspect = activeAspect;
                self._updateDescriptor(self._getPartDescriptorCollection());
            }
            //else {
            //    if (self._visualizer === 'SetEditor') {
            //        //we have to react to all tab change...
            //        self._updateDescriptor(self._getPartDescriptorCollection());
            //    }
            //} //TODO right now we cannot create objects in setEditor so we do not need this functionality
        });

        WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_VISUALIZER, function (model, activeVisualizer) {
            if (self._visualizer !== activeVisualizer) {
                self._visualizer = activeVisualizer;
                self._updateDescriptor(self._getPartDescriptorCollection());
            }
        });

        this._nodeEventHandling = function (events) {
            var metaChange = false,
                metaNodes = self._client.getAllMetaNodes() || [],
                metaPaths = [],
                i;

            for (i = 0; i < metaNodes.length; i += 1) {
                metaPaths.push(metaNodes[i].getId());
            }
            metaPaths.push(CONSTANTS.PROJECT_ROOT_ID);

            for (i = 0; i < events.length; i += 1) {
                if (metaPaths.indexOf(events[i].eid) !== -1) {
                    metaChange = true;
                    break;
                }
            }

            if (metaChange) {
                self._updateDescriptor(self._getPartDescriptorCollection());
            } else {
                self._updateDecorators();
            }

        };

        this._client.addUI(self, self._nodeEventHandling, this._guid);
        this._client.updateTerritory(this._guid, this._territoryRules);
    };

    PartBrowserControl.prototype._defaultCompare = function (a, b) {
        var result = a.name.localeCompare(b.name);
        // sort alphabetically based on name first
        if (result) {
            return result;
        } else {
            return a.id.localeCompare(b.id);
        }
    };

    PartBrowserControl.prototype._updateDescriptor = function (newDescriptor) {
        var descriptor = newDescriptor || {},
            keys,
            i,
            self = this,
            div,
            newTerritoryRules;

        // TODO: later we should apply project specific sorting if it is defined.
        keys = Object.keys(newDescriptor || {})         // get the descriptor keys or empty object
            .map(function (key) { return descriptor[key]; })  // turn the object into an array
            .sort(self._defaultCompare)                 // sort the objects, using the default compare
            .map(function (value, index) { return value.id; }); // get only the ids

        //add and update
        for (i = 0; i < keys.length; i += 1) {
            if (!this._descriptorCollection[keys[i]]) {
                //new item
                this._partInstances[keys[i]] = this._partBrowserView.addPart(keys[i], newDescriptor[keys[i]]);
            } else if (this._descriptorCollection[keys[i]].decorator !== newDescriptor[keys[i]].decorator) {
                this._partInstances[keys[i]] = this._partBrowserView.updatePart(keys[i], newDescriptor[keys[i]]);
            }

            if (!this._descriptorCollection[keys[i]] ||
                (this._descriptorCollection[keys[i]].visibility !== newDescriptor[keys[i]].visibility)) {
                div = this._partBrowserView._getPartDiv(keys[i]);
                if (newDescriptor[keys[i]].visibility === 'hidden') {
                    div.hide();
                } else if (newDescriptor[keys[i]].visibility === 'visible') {
                    div.show();
                    this._partBrowserView.setEnabled(keys[i], true);
                } else {
                    div.show();
                    this._partBrowserView.setEnabled(keys[i], false);
                }
            }
        }

        //remove
        keys = Object.keys(this._descriptorCollection);

        for (i = 0; i < keys.length; i += 1) {
            if (!newDescriptor[keys[i]]) {
                this._partBrowserView.removePart(keys[i]);
                delete this._partInstances[keys[i]];
            }
        }

        this._descriptorCollection = newDescriptor;
        newTerritoryRules = this._getTerritoryPatterns();
        if (JSON.stringify(this._territoryRules) !== JSON.stringify(newTerritoryRules)) {
            this._territoryRules = newTerritoryRules;
            setTimeout(function () {
                self._client.updateTerritory(self._guid, self._territoryRules);
            }, 0);
        } else {
            this._updateDecorators();
        }
    };

    PartBrowserControl.prototype._getPartDescriptorCollection = function () {
        var containerNode = this._client.getNode(this._containerNodeId),
            metaNodes = this._client.getAllMetaNodes(),
            descriptorCollection = {},
            descriptor,
            validInfo,
            keys,
            i;
        //getSetName = function () {
        //    var setNamesOrdered = (containerNode.getSetNames() || []).sort(),
        //        tabId = WebGMEGlobal.State.getActiveTab();
        //
        //    if (tabId < setNamesOrdered.length) {
        //        return setNamesOrdered[tabId];
        //    }
        //
        //    return null;
        //}; not used yet

        for (i = 0; i < metaNodes.length; i += 1) {
            descriptor = this._getPartDescriptor(metaNodes[i].getId());
            if (descriptor) {
                descriptorCollection[metaNodes[i].getId()] = this._getPartDescriptor(metaNodes[i].getId());
                descriptorCollection[metaNodes[i].getId()].visibility = 'hidden';
            }
        }

        if (containerNode) {
            if (this._visualizer === 'GraphViz') {
                //do nothing as partBrowser should not have any element in GraphViz
                validInfo = {};
            } else if (this._visualizer === 'SetEditor') {
                //i = getSetName();
                //if (i) {
                //    validInfo = containerNode.getValidSetMemberTypesDetailed(i);
                //} else {
                //    validInfo = {};
                //} //TODO now we cannot create elements in set editor
                validInfo = {};
            } else if (this._visualizer === 'METAAspect') {
                //here we should override the container node to the META container node - ROOT as of now
                containerNode = this._client.getNode(CONSTANTS.PROJECT_ROOT_ID);
                validInfo = containerNode.getValidChildrenTypesDetailed(null, true);
            } else {
                //default is the containment based elements
                validInfo = containerNode.getValidChildrenTypesDetailed(this._aspect);
            }

            keys = Object.keys(validInfo);

            for (i = 0; i < keys.length; i += 1) {
                if (validInfo[keys[i]]) {
                    descriptorCollection[keys[i]].visibility = 'visible';
                } else {
                    descriptorCollection[keys[i]].visibility = 'grayed';
                }
            }
        }

        return descriptorCollection;
    };

    PartBrowserControl.prototype._getTerritoryPatterns = function () {
        var patterns = {'': {children: 0}},
            keys,
            query,
            i;

        if (this._containerNodeId) {
            patterns[this._containerNodeId] = {children: 0};

            keys = Object.keys(this._partInstances || {}).sort();
            for (i = 0; i < keys.length; i += 1) {
                if (this._partInstances[keys[i]]) {
                    //console.log(this._partInstances[keys[i]].getTerritoryQuery());
                    query = this._partInstances[keys[i]].getTerritoryQuery() || {};

                    if (query[keys[i]]) {
                        patterns[keys[i]] = query[keys[i]];
                    }
                }
            }
        }

        return patterns;
    };

    PartBrowserControl.prototype._getObjectDescriptor = function (nodeId) {
        var nodeObj = this._client.getNode(nodeId),
            objDescriptor;

        if (nodeObj) {
            objDescriptor = {};

            objDescriptor.id = nodeObj.getId();
            objDescriptor.decorator = nodeObj.getRegistry(REGISTRY_KEYS.DECORATOR) || DEFAULT_DECORATOR;
            objDescriptor.name = nodeObj.getAttribute(nodePropertyNames.Attributes.name);
        } else {
            this._logger.error('Node not loaded', nodeId);
        }

        return objDescriptor;
    };

    PartBrowserControl.prototype._getItemDecorator = function (decorator) {
        var result;

        result = this._client.decoratorManager.getDecoratorForWidget(decorator, WIDGET_NAME);
        if (!result) {
            result = this._client.decoratorManager.getDecoratorForWidget(DEFAULT_DECORATOR, WIDGET_NAME);
        }

        return result;
    };

    PartBrowserControl.prototype._getPartDescriptor = function (id) {
        var desc = this._getObjectDescriptor(id);

        if (desc) {
            desc.decoratorClass = this._getItemDecorator(desc.decorator);
            desc.control = this;
            desc.metaInfo = {};
            desc.metaInfo[CONSTANTS.GME_ID] = id;
            desc.preferencesHelper = PreferencesHelper.getPreferences();
            desc.aspect = this._aspect;
        }

        return desc;
    };

    PartBrowserControl.prototype.registerComponentIDForPartID = function (componentID, partId) {
        this._componentIDPartIDMap[componentID] = this._componentIDPartIDMap[componentID] || [];
        if (this._componentIDPartIDMap[componentID].indexOf(partId) === -1) {
            this._componentIDPartIDMap[componentID].push(partId);
        }
    };

    PartBrowserControl.prototype.unregisterComponentIDFromPartID = function (componentID, partId) {
        var idx;

        if (this._componentIDPartIDMap && this._componentIDPartIDMap[componentID]) {
            idx = this._componentIDPartIDMap[componentID].indexOf(partId);
            if (idx !== -1) {
                this._componentIDPartIDMap[componentID].splice(idx, 1);

                if (this._componentIDPartIDMap[componentID].length === 0) {
                    delete this._componentIDPartIDMap[componentID];
                }
            }
        }
    };

    PartBrowserControl.prototype._initDragDropFeatures = function () {
        var dragEffects = this._partBrowserView.DRAG_EFFECTS;

        this._partBrowserView.getDragEffects = function (/*el*/) {
            return [dragEffects.DRAG_CREATE_INSTANCE];
        };

        this._partBrowserView.getDragItems = function (el) {
            return [el.attr('id')];
        };
    };

    PartBrowserControl.prototype._updateDecorators = function () {
        var i,
            keys = Object.keys(this._partInstances || {});

        for (i = 0; i < keys.length; i += 1) {
            if (this._descriptorCollection[keys[i]] && this._descriptorCollection[keys[i]].visibility !== 'hidden') {
                this._partInstances[keys[i]].update();
            }
        }
    };

    return PartBrowserControl;
});<|endoftext|>


<commit_before>var request  = require('request'),
    _        = require('lodash');

/**
 * OSMRegions API wrapper
 *
 * @param options Configuration options
 * @return Instance of {@link OSMRegions}
 */
function OSMRegions (options) {

  if (!options) {
    options = {};
  }

  /*if (!options.apiKey) {
    throw new Error('API Key not set');
  }*/

  this.endpoint = options.endpoint || 'http://osm.nearest.place/';

}

module.exports = OSMRegions;

/**
 * Get Regions based on Lat/Lng
 * @param  {[object]}   options  must contain the following properties:
 *          * lat: Latitude
 *          * lng: Longitude
 *          * fields: Return the full response
 */
OSMRegions.prototype.getRegions = function (options) {

  var self = this;

  if(!options.lat && !options.lng) {
    throw new Error('Lat or Lng not set!');
  }

  options.fields = options.fields.split(',');
  options.fields.push('osm_id');

  return new Promise(_.bind(function(resolve, reject) {
    this.execute('region', {lat: options.lat, lng: options.lng, fields: _.uniq(options.fields).join()})
      .then(function(response) {
        resolve(self._parse(response));
      })
      .catch(function(err) {
        reject(err);
      });
  }, this));
};

/**
 * Return a region based on the osm_id
 * @param  {[object]}   options  Can contain the following properties:
 *          * id: osm_id
 *          * fields: (way)
 */
OSMRegions.prototype.getId = function (options) {

  var self = this;

  if(!options.id) {
    throw new Error('Id not set!');
  }

  options.fields = this._fields(options.fields);

  return new Promise(_.bind(function(resolve, reject) {
    this.execute('get', {id: options.id, fields: options.fields})
      .then(function(response) {
        resolve(self._parse(response));
      })
      .catch(function(err) {
        reject(err);
      });
  }, this));
};

/**
 * Return parsed fields
 * @param  {[object]}   response  A response from the API
 */
OSMRegions.prototype._fields = function (fields) {
  if(typeof fields === 'object') {
    return fields.join();
  }
  return fields;
};

/**
 * Return parsed response
 * @param  {[object]}   response  A response from the API
 */
OSMRegions.prototype._parse = function (response) {

  _.each(response,function(reg,i){
    if(reg.way && typeof reg.way === 'string') {
      response[i].way = JSON.parse(reg.way);
    }
    if(reg.center && typeof reg.center === 'string') {
      response[i].center = JSON.parse(reg.center);
    }
    if(reg.bbox && typeof reg.bbox === 'string') {
      response[i].bbox = JSON.parse(reg.bbox);
    }
    if(reg.osm_id && typeof reg.osm_id === 'string') {
      response[i].osm_id = parseInt(reg.osm_id);
    }
  });

  return response;

};

/**
 * Sends a given request as a JSON object to the OSM API and returns
 * a promise which if resolved will contain the resulting JSON object.
 *
 * @param  {[type]}   method   OSM API method to call (regions | get)
 * @param  {[type]}   params   Object containg parameters to call the API with
 * @param  {Function} Promise
 */
OSMRegions.prototype.execute = function (method, params) {
  return new Promise(_.bind(function(resolve, reject) {

    //var finalParams = _.extend({ key:  this.apiKey }, params);
    var finalParams = params;

    options = {
      url: this.endpoint + method,
      qs: finalParams
    };

    request.get(options, function (error, response, body) {
      if (response.statusCode !== 200) {
        reject('Unable to connect to the API endpoint ' + options.url);
      } else if (response.body.error) {
        reject(response.body.error + '. Message: ' + response.body.message);
      }
      if(body){
        resolve(JSON.parse(response.body));
      }
    });
  }, this));

};
<commit_msg>Fixed fields bug w/ empty<commit_after>var request  = require('request'),
    _        = require('lodash');

/**
 * OSMRegions API wrapper
 *
 * @param options Configuration options
 * @return Instance of {@link OSMRegions}
 */
function OSMRegions (options) {

  if (!options) {
    options = {};
  }

  /*if (!options.apiKey) {
    throw new Error('API Key not set');
  }*/

  this.endpoint = options.endpoint || 'http://osm.nearest.place/';

}

module.exports = OSMRegions;

/**
 * Get Regions based on Lat/Lng
 * @param  {[object]}   options  must contain the following properties:
 *          * lat: Latitude
 *          * lng: Longitude
 *          * fields: Return the full response
 */
OSMRegions.prototype.getRegions = function (options) {

  var self = this;

  if(!options.lat && !options.lng) {
    throw new Error('Lat or Lng not set!');
  }

  options.fields = this._fields(options.fields);
  if(!options.fields) {
    options.fields = [];
  } else {
    options.fields = options.fields.split(',');
  }
  options.fields.push('osm_id');

  return new Promise(_.bind(function(resolve, reject) {
    this.execute('region', {lat: options.lat, lng: options.lng, fields: _.uniq(options.fields).join()})
      .then(function(response) {
        resolve(self._parse(response));
      })
      .catch(function(err) {
        reject(err);
      });
  }, this));
};

/**
 * Return a region based on the osm_id
 * @param  {[object]}   options  Can contain the following properties:
 *          * id: osm_id
 *          * fields: (way)
 */
OSMRegions.prototype.getId = function (options) {

  var self = this;

  if(!options.id) {
    throw new Error('Id not set!');
  }

  options.fields = this._fields(options.fields);

  return new Promise(_.bind(function(resolve, reject) {
    this.execute('get', {id: options.id, fields: options.fields})
      .then(function(response) {
        resolve(self._parse(response));
      })
      .catch(function(err) {
        reject(err);
      });
  }, this));
};

/**
 * Return parsed fields
 * @param  {[object]}   response  A response from the API
 */
OSMRegions.prototype._fields = function (fields) {
  if(!fields) {
    return '';
  }
  if(typeof fields === 'object') {
    return fields.join();
  }
  return fields;
};

/**
 * Return parsed response
 * @param  {[object]}   response  A response from the API
 */
OSMRegions.prototype._parse = function (response) {

  _.each(response,function(reg,i){
    if(reg.way && typeof reg.way === 'string') {
      response[i].way = JSON.parse(reg.way);
    }
    if(reg.center && typeof reg.center === 'string') {
      response[i].center = JSON.parse(reg.center);
    }
    if(reg.bbox && typeof reg.bbox === 'string') {
      response[i].bbox = JSON.parse(reg.bbox);
    }
    if(reg.osm_id && typeof reg.osm_id === 'string') {
      response[i].osm_id = parseInt(reg.osm_id);
    }
  });

  return response;

};

/**
 * Sends a given request as a JSON object to the OSM API and returns
 * a promise which if resolved will contain the resulting JSON object.
 *
 * @param  {[type]}   method   OSM API method to call (regions | get)
 * @param  {[type]}   params   Object containg parameters to call the API with
 * @param  {Function} Promise
 */
OSMRegions.prototype.execute = function (method, params) {
  return new Promise(_.bind(function(resolve, reject) {

    //var finalParams = _.extend({ key:  this.apiKey }, params);
    var finalParams = params;

    options = {
      url: this.endpoint + method,
      qs: finalParams
    };

    request.get(options, function (error, response, body) {
      if (response.statusCode !== 200) {
        reject('Unable to connect to the API endpoint ' + options.url);
      } else if (response.body.error) {
        reject(response.body.error + '. Message: ' + response.body.message);
      }
      if(body){
        resolve(JSON.parse(response.body));
      }
    });
  }, this));

};
<|endoftext|>


<commit_before>'use strict';

// Requirements
var npm = require('npm');
var changelog = require('changelog');
var cmp = require('semver-compare');
var async = require('async');
var chalk = require('chalk');

var rslt = {};
var showMax = false;

function worker(packages, unwanted, global) {
	if (unwanted) {
		showMax = true;
	}
	npm.load({
		global : !!global,
		parseable: false
	}, function(err, npm) {
		if (err) throw err;
		npm.commands.outdated(packages, function(err, data) {
			if (err) throw err;
			rslt = {};
			// For each npm outdated module
			async.forEachOf(data, workerChangelog, prettyData);

		});
	});
}

function workerChangelog(value, key, callback) {
	// Generate changelog
	changelog.generate(value[1])
		.then(function(data) {
			var tmpArray = [];
			// Keep only changelog versions between the current and the target
			if (data.versions.length && value[2]) {
				data.versions.forEach(function(version) {
					if (cmp(version.version, value[2]) === 1 && (cmp(version.version, value[3]) <= 0 || showMax)) {
						tmpArray.push(version);
					}
				});
			}
			data.versions = tmpArray;
			// Generate terminal output
			rslt[value[1]] = changelog.terminal(data);
			callback();
		})
		.catch(function(err) {
			if (typeof err === 'string') {
				console.error(err);
			}
			else {
				throw err;
			}
			callback();
		})
		.done();

}

function prettyData(err) {
	if (err) throw err;
	async.forEachOf(rslt, function(value, key) {
		if (value.length) {
			printData('\r');
			printData(chalk.red(key));
			printData(value);
		}
	});
}

function printData(data) {
	console.info(data);
}

module.exports = worker;<commit_msg>fix(codacy): fix coding style<commit_after>'use strict';

// Requirements
var npm = require('npm');
var changelog = require('changelog');
var cmp = require('semver-compare');
var async = require('async');
var chalk = require('chalk');

var rslt = {};
var showMax = false;

function worker(packages, unwanted, global) {
	if (unwanted) {
		showMax = true;
	}
	npm.load({
		global: !!global,
		parseable: false
	}, function(err, npm) {
		if (err) {
			throw err;
		}
		npm.commands.outdated(packages, function(err, data) {
			if (err) {
				throw err;
			}
			rslt = {};
			// For each npm outdated module
			async.forEachOf(data, workerChangelog, prettyData);

		});
	});
}

function workerChangelog(value, key, callback) {
	// Generate changelog
	changelog.generate(value[1])
		.then(function(data) {
			var tmpArray = [];
			// Keep only changelog versions between the current and the target
			if (data.versions.length && value[2]) {
				data.versions.forEach(function(version) {
					if (cmp(version.version, value[2]) === 1 && (cmp(version.version, value[3]) <= 0 || showMax)) {
						tmpArray.push(version);
					}
				});
			}
			data.versions = tmpArray;
			// Generate terminal output
			rslt[value[1]] = changelog.terminal(data);
			callback();
		})
		.catch(function(err) {
			if (typeof err === 'string') {
				console.error(err);
			}
			else {
				throw err;
			}
			callback();
		})
		.done();

}

function prettyData(err) {
	if (err) {
		throw err;
	}
	async.forEachOf(rslt, function(value, key) {
		if (value.length) {
			printData('\r');
			printData(chalk.red(key));
			printData(value);
		}
	});
}

function printData(data) {
	console.info(data);
}

module.exports = worker;<|endoftext|>


<commit_before>/**
 * conjoon
 * (c) 2002-2012 siteartwork.de/conjoon.org
 * licensing@conjoon.org
 *
 * $Author$
 * $Id$
 * $Date$
 * $Revision$
 * $LastChangedDate$
 * $LastChangedBy$
 * $URL$
 */

com.conjoon.groupware.email.EmailAccountWizard = Ext.extend(Ext.ux.Wiz, {

    /**
     * @param {Object} requestId The current id of the ajax request that stores the
     * form values.
     */
    requestId : null,

    /**
     * Inits this component.
     */
    initComponent : function()
    {

        this.cards = [
            new Ext.ux.Wiz.Card({
                title        : com.conjoon.Gettext.gettext("Welcome"),
                header       : false,
                border       : false,
                monitorValid : false,
                items        : [{
                    border    : false,
                    bodyStyle : 'background-color:#F6F6F6;',
                    html      : '
'
                                +com.conjoon.Gettext.gettext("You need to have an email account configured for sending and receiving email messages.

This assistant will guide you through the neccessary steps for collecting the needed account information. If you are unsure about specific information asked by this assistant, please contact your email provider.")
                                +'
'
                }]
            }),

            new com.conjoon.groupware.email.wizard.ServerTypeCard(),
            new com.conjoon.groupware.email.EmailAccountWizardNameCard(),
            new com.conjoon.groupware.email.wizard.ServerInboxCard(),
            new com.conjoon.groupware.email.wizard.ServerOutboxCard(),
            new com.conjoon.groupware.email.EmailAccountWizardAccountNameCard(),
            new com.conjoon.groupware.email.EmailAccountWizardFinishCard()
        ];
        this.cls = 'com-conjoon-groupware-email-EmailAccountWizard-panelBackground';
        this.title        = com.conjoon.Gettext.gettext("Email account assistant");
        this.headerConfig = {
            title : com.conjoon.Gettext.gettext("Create a new Email-Account")
        };

        com.conjoon.groupware.email.EmailAccountWizard.superclass.initComponent.call(this);
    },

    /**
     * Callback for the "finish" button. Collects all form values and sends them to the server
     * to create a new email account.
     */
    onFinish : function()
    {
        var values = {};
        var formValues = {};
        for (var i = 0, len = this.cards.length; i < len; i++) {
            formValues = this.cards[i].form.getValues(false);
            for (var a in formValues) {
                values[a] = formValues[a];
            }
        }

        values['isOutboxAuth'] = values['isOutboxAuth'] == 'on' ? true : false;

        if (!values['isOutboxAuth']) {
            values['usernameOutbox'] = '';
            values['passwordOutbox'] = '';
        }

        if (values['inboxConnectionType'] != 'SSL' && values['inboxConnectionType'] != 'TLS') {
            values['inboxConnectionType'] = null;
        }

        if (values['outboxConnectionType'] != 'SSL' && values['outboxConnectionType'] != 'TLS') {
            values['outboxConnectionType'] = null;
        }

        this.switchDialogState(false);

        this.requestId = Ext.Ajax.request({
            url               : './groupware/email.account/add.email.account/format/json',
            params            : values,
            success           : this.onAddSuccess,
            failure           : this.onAddFailure,
            scope             : this
        });
    },

    /**
     * Callback for a succesfull ajax request. Successfull means that the server
     * could handle the request and that no connection problems occured.
     * The response may report a failure though, due to connection problems
     * to the database or similiar.
     * The response will return the interger-value of the newly added account in
     * the database, otherwise it will be empty or hoolding an error message.
     * If the key of the newly created data is being returned, the account will be
     * added to the accountstore.
     *
     * @param {Object} response The response object returned by the server.
     * @param {Object} options The options used to initiate the request.
     */
    onAddSuccess : function(response, options)
    {
        var json = com.conjoon.util.Json;

        // first off, check the response if it contains any error
        if (json.isError(response.responseText)) {
            this.onAddFailure(response, options);
            return;
        }

        // fetch the response values
        var responseValues = json.getResponseValues(response.responseText);
        var account        = responseValues.account;
        var rootFolder     = responseValues.rootFolder;
        var accountStore   = com.conjoon.groupware.email.AccountStore.getInstance();

        var rec = com.conjoon.util.Record.convertTo(
            com.conjoon.groupware.email.AccountRecord,
            account, account.id
        );

        accountStore.addSorted(rec);

        if (rootFolder && rootFolder.id) {
            Ext.ux.util.MessageBus.publish(
                'com.conjoon.groupware.email.account.added',
                {account : rec, rootFolder : rootFolder}
            );
        }

        this.switchDialogState(true);
        this.requestId = null;
        this.close();
    },

    /**
     * Callback for an errorneous Ajax request. This method gets called
     * whenever the request couldn't be processed, due to connection or
     * server problems.
     *
     * @param {Object} response The response object returned by the server.
     * @param {Object} options The options used to initiate the request.
     */
    onAddFailure : function(response, options)
    {
        this.switchDialogState(true);

        com.conjoon.groupware.ResponseInspector.handleFailure(response);

        this.requestId = null;
    }

});

com.conjoon.groupware.email.EmailAccountWizardNameCard = Ext.extend(Ext.ux.Wiz.Card, {

    nameField : null,
    addressField : null,

    initComponent : function()
    {
        this.monitorValid = true;

        this.baseCls    = 'x-small-editor';
        this.labelWidth = 80;

        this.defaultType = 'textfield';
        this.title = com.conjoon.Gettext.gettext("Personal data");
        this.defaults = {
            labelStyle : 'width:80px;font-size:11px',
            anchor: '100%'
         };

        this.nameField = new Ext.form.TextField({
            fieldLabel : com.conjoon.Gettext.gettext("Your name"),
            allowBlank : false,
            name       : 'userName'
        });

        this.addressField = new Ext.form.TextField({
            fieldLabel : com.conjoon.Gettext.gettext("Email address"),
            allowBlank : false,
            validator  : Ext.form.VTypes.email,
            name       : 'address'
        });

        this.items = [
            new com.conjoon.groupware.util.FormIntro({
                style     : 'margin:10px 0 5px 0;',
                labelText : com.conjoon.Gettext.gettext("Personal data"),
                text      : com.conjoon.Gettext.gettext("Specify your real name and your email address here. This information will be visible to the recipients of your messages.")
            }),
            this.nameField,
            this.addressField
        ];

        com.conjoon.groupware.email.EmailAccountWizardNameCard.superclass.initComponent.call(this);
    }
});

com.conjoon.groupware.email.EmailAccountWizardAccountNameCard = Ext.extend(Ext.ux.Wiz.Card, {

    nameField : null,
    accountStore : null,

    initComponent : function()
    {
        this.monitorValid = true;

        this.accountStore = com.conjoon.groupware.email.AccountStore.getInstance();

         this.baseCls    = 'x-small-editor';
        this.labelWidth = 75;

        this.defaultType = 'textfield';
        this.title = com.conjoon.Gettext.gettext("Account name");
        this.defaults = {
            labelStyle : 'width:75px;font-size:11px',
            anchor: '100%'
         };

        this.nameField = new Ext.form.TextField({
            fieldLabel : com.conjoon.Gettext.gettext("Name"),
            allowBlank : false,
            validator  : this.validateAccountName.createDelegate(this),
            name       : 'name'
        });

        this.items = [
            new com.conjoon.groupware.util.FormIntro({
                style     : 'margin:10px 0 5px 0;',
                labelText : com.conjoon.Gettext.gettext("Account name"),
                text      : com.conjoon.Gettext.gettext("Specify a unique name for this account. This name will be used later on to identify this account. The name must not be already existing.")
            }),
            this.nameField
        ];

        com.conjoon.groupware.email.EmailAccountWizardAccountNameCard.superclass.initComponent.call(this);
    },

    validateAccountName : function(value)
    {
        value = value.trim().toLowerCase();

        if (value === "") {
            return false;
        } else {
            /**
             * @ext-bug 2.0.2 seems to look for any match
             */
            //var index = this.accountStore.find('name', value, 0, false, false);
            var recs = this.accountStore.getRange();
            for (var i = 0, len = recs.length; i < len; i++) {
                if (recs[i].get('name').toLowerCase() === value) {
                    return false;
                }
            }

            return true;
        }

        return true;
    }

});

com.conjoon.groupware.email.EmailAccountWizardFinishCard = Ext.extend(Ext.ux.Wiz.Card, {

    templates    : null,
    contentPanel : null,

    initComponent : function()
    {
        this.templates =  {
            master : new Ext.Template(
                '
'+
                    '
'+
                    '
'+com.conjoon.Gettext.gettext("Server type")+':	{protocol}
'+
                    '
'+com.conjoon.Gettext.gettext("Account name")+':	{name:htmlEncode}
'+
                    '
'+com.conjoon.Gettext.gettext("Your name")+':	{userName:htmlEncode}
'+
                    '
'+com.conjoon.Gettext.gettext("Email address")+':	{address:htmlEncode}
'+
                    '
'+com.conjoon.Gettext.gettext("Inbox host")+':	{serverInbox:htmlEncode}:{portInbox}
'+
                    '
'+com.conjoon.Gettext.gettext("Inbox user name")+':	{usernameInbox:htmlEncode}
'+
                    '
'+com.conjoon.Gettext.gettext("Inbox password")+':	{passwordInbox}
'+
                    '
'+com.conjoon.Gettext.gettext("Secure connection for inbox")+':	{inboxConnectionType}
'+
                    '
'+com.conjoon.Gettext.gettext("Outbox host")+':	{serverOutbox:htmlEncode}:{portOutbox}
'+
                    '
'+com.conjoon.Gettext.gettext("Outbox authentication")+':	{isOutboxAuth}
'+
                    '{auth_template}'+
                    '
'+
                '
'
            ),
            auth : new Ext.Template(
                '
'+com.conjoon.Gettext.gettext("Outbox user name")+':	{usernameOutbox:htmlEncode}
'+
                '
'+com.conjoon.Gettext.gettext("Outbox password")+':	{passwordOutbox}
'+
                '
'+com.conjoon.Gettext.gettext("Secure connection for outbox")+':	{outboxConnectionType}
'
            )
        };

        var ts = this.templates;

        for(var k in ts){
            ts[k].compile();
        }

        this.border = false;
        this.monitorValid = false;

        this.title = com.conjoon.Gettext.gettext("Confirm");

        this.contentPanel = new Ext.Panel({
            style : 'margin:0 0 0 20px'
        });

        this.items = [{
                border    : false,
                html      : "
"+com.conjoon.Gettext.gettext("The new account can now be created.
Please verify your submitted data and correct them if neccessary.")+"
",
                bodyStyle : 'background-color:#F6F6F6;margin:10px 0 10px 0'
            },
            this.contentPanel
        ];

        this.contentPanel.on('render', this.addContent, this, {single : true});

        com.conjoon.groupware.email.EmailAccountWizardFinishCard.superclass.initComponent.call(this);
    },

    addContent : function()
    {
        var ts = this.templates;

        var authTemplate = "";

        var items = this.ownerCt.items;

        var values = {};
        var formValues = {};
        for (var i = 0, len = items.length; i < len; i++) {
            formValues = items.get(i).form.getValues(false);
            for (var a in formValues) {
                values[a] = formValues[a];
            }
        }

        if (values.isOutboxAuth == 'on') {
            authTemplate = ts.auth.apply({
                usernameOutbox       : values.usernameOutbox,
                passwordOutbox       : "****",
                outboxConnectionType : values.outboxConnectionType == 'SSL'
                                        || values.outboxConnectionType == 'TLS'
                                      ? String.format(
                                            com.conjoon.Gettext.gettext("Uses {0}"),
                                            values.outboxConnectionType
                                        )
                                      : com.conjoon.Gettext.gettext("No")
            });
        }

        var html = ts.master.apply({
            portInbox     : values.portInbox,
            portOutbox    : values.portOutbox,
            protocol      : values.protocol,
            name          : values.name,
            userName      : values.userName,
            address       : values.address,
            serverInbox   : values.serverInbox,
            usernameInbox : values.usernameInbox,
            passwordInbox : "****",
            serverOutbox  : values.serverOutbox,
            isOutboxAuth  : values.isOutboxAuth == 'on'
                            ? com.conjoon.Gettext.gettext("Yes")
                            : com.conjoon.Gettext.gettext("No"),
            inboxConnectionType :  values.inboxConnectionType == 'SSL'
                                   || values.inboxConnectionType == 'TLS'
                                   ? String.format(
                                         com.conjoon.Gettext.gettext("Uses {0}"),
                                         values.inboxConnectionType
                                     )
                                   : com.conjoon.Gettext.gettext("No"),
            auth_template : authTemplate
        });

        this.contentPanel.el.update(html);

        this.on('show', this.addContent, this);
    }

});<commit_msg>[Email module - client] - enhancement: removed Server Type Card from Email Account Assistant (closes CN-488)<commit_after>/**
 * conjoon
 * (c) 2002-2012 siteartwork.de/conjoon.org
 * licensing@conjoon.org
 *
 * $Author$
 * $Id$
 * $Date$
 * $Revision$
 * $LastChangedDate$
 * $LastChangedBy$
 * $URL$
 */

com.conjoon.groupware.email.EmailAccountWizard = Ext.extend(Ext.ux.Wiz, {

    /**
     * @param {Object} requestId The current id of the ajax request that stores the
     * form values.
     */
    requestId : null,

    /**
     * Inits this component.
     */
    initComponent : function()
    {

        this.cards = [
            new Ext.ux.Wiz.Card({
                title        : com.conjoon.Gettext.gettext("Welcome"),
                header       : false,
                border       : false,
                monitorValid : false,
                items        : [{
                    border    : false,
                    bodyStyle : 'background-color:#F6F6F6;',
                    html      : '
'
                                +com.conjoon.Gettext.gettext("You need to have an email account configured for sending and receiving email messages.

This assistant will guide you through the neccessary steps for collecting the needed account information. If you are unsure about specific information asked by this assistant, please contact your email provider.")
                                +'
'
                }]
            }),

            //new com.conjoon.groupware.email.wizard.ServerTypeCard(),
            new com.conjoon.groupware.email.EmailAccountWizardNameCard(),
            new com.conjoon.groupware.email.wizard.ServerInboxCard(),
            new com.conjoon.groupware.email.wizard.ServerOutboxCard(),
            new com.conjoon.groupware.email.EmailAccountWizardAccountNameCard(),
            new com.conjoon.groupware.email.EmailAccountWizardFinishCard()
        ];
        this.cls = 'com-conjoon-groupware-email-EmailAccountWizard-panelBackground';
        this.title        = com.conjoon.Gettext.gettext("Email account assistant");
        this.headerConfig = {
            title : com.conjoon.Gettext.gettext("Create a new Email-Account")
        };

        com.conjoon.groupware.email.EmailAccountWizard.superclass.initComponent.call(this);
    },

    /**
     * Callback for the "finish" button. Collects all form values and sends them to the server
     * to create a new email account.
     */
    onFinish : function()
    {
        var values = {};
        var formValues = {};
        for (var i = 0, len = this.cards.length; i < len; i++) {
            formValues = this.cards[i].form.getValues(false);
            for (var a in formValues) {
                values[a] = formValues[a];
            }
        }

        // remove me
        values['protocol'] = 'POP3';

        values['isOutboxAuth'] = values['isOutboxAuth'] == 'on' ? true : false;

        if (!values['isOutboxAuth']) {
            values['usernameOutbox'] = '';
            values['passwordOutbox'] = '';
        }

        if (values['inboxConnectionType'] != 'SSL' && values['inboxConnectionType'] != 'TLS') {
            values['inboxConnectionType'] = null;
        }

        if (values['outboxConnectionType'] != 'SSL' && values['outboxConnectionType'] != 'TLS') {
            values['outboxConnectionType'] = null;
        }

        this.switchDialogState(false);

        this.requestId = Ext.Ajax.request({
            url               : './groupware/email.account/add.email.account/format/json',
            params            : values,
            success           : this.onAddSuccess,
            failure           : this.onAddFailure,
            scope             : this
        });
    },

    /**
     * Callback for a succesfull ajax request. Successfull means that the server
     * could handle the request and that no connection problems occured.
     * The response may report a failure though, due to connection problems
     * to the database or similiar.
     * The response will return the interger-value of the newly added account in
     * the database, otherwise it will be empty or hoolding an error message.
     * If the key of the newly created data is being returned, the account will be
     * added to the accountstore.
     *
     * @param {Object} response The response object returned by the server.
     * @param {Object} options The options used to initiate the request.
     */
    onAddSuccess : function(response, options)
    {
        var json = com.conjoon.util.Json;

        // first off, check the response if it contains any error
        if (json.isError(response.responseText)) {
            this.onAddFailure(response, options);
            return;
        }

        // fetch the response values
        var responseValues = json.getResponseValues(response.responseText);
        var account        = responseValues.account;
        var rootFolder     = responseValues.rootFolder;
        var accountStore   = com.conjoon.groupware.email.AccountStore.getInstance();

        var rec = com.conjoon.util.Record.convertTo(
            com.conjoon.groupware.email.AccountRecord,
            account, account.id
        );

        accountStore.addSorted(rec);

        if (rootFolder && rootFolder.id) {
            Ext.ux.util.MessageBus.publish(
                'com.conjoon.groupware.email.account.added',
                {account : rec, rootFolder : rootFolder}
            );
        }

        this.switchDialogState(true);
        this.requestId = null;
        this.close();
    },

    /**
     * Callback for an errorneous Ajax request. This method gets called
     * whenever the request couldn't be processed, due to connection or
     * server problems.
     *
     * @param {Object} response The response object returned by the server.
     * @param {Object} options The options used to initiate the request.
     */
    onAddFailure : function(response, options)
    {
        this.switchDialogState(true);

        com.conjoon.groupware.ResponseInspector.handleFailure(response);

        this.requestId = null;
    }

});

com.conjoon.groupware.email.EmailAccountWizardNameCard = Ext.extend(Ext.ux.Wiz.Card, {

    nameField : null,
    addressField : null,

    initComponent : function()
    {
        this.monitorValid = true;

        this.baseCls    = 'x-small-editor';
        this.labelWidth = 80;

        this.defaultType = 'textfield';
        this.title = com.conjoon.Gettext.gettext("Personal data");
        this.defaults = {
            labelStyle : 'width:80px;font-size:11px',
            anchor: '100%'
         };

        this.nameField = new Ext.form.TextField({
            fieldLabel : com.conjoon.Gettext.gettext("Your name"),
            allowBlank : false,
            name       : 'userName'
        });

        this.addressField = new Ext.form.TextField({
            fieldLabel : com.conjoon.Gettext.gettext("Email address"),
            allowBlank : false,
            validator  : Ext.form.VTypes.email,
            name       : 'address'
        });

        this.items = [
            new com.conjoon.groupware.util.FormIntro({
                style     : 'margin:10px 0 5px 0;',
                labelText : com.conjoon.Gettext.gettext("Personal data"),
                text      : com.conjoon.Gettext.gettext("Specify your real name and your email address here. This information will be visible to the recipients of your messages.")
            }),
            this.nameField,
            this.addressField
        ];

        com.conjoon.groupware.email.EmailAccountWizardNameCard.superclass.initComponent.call(this);
    }
});

com.conjoon.groupware.email.EmailAccountWizardAccountNameCard = Ext.extend(Ext.ux.Wiz.Card, {

    nameField : null,
    accountStore : null,

    initComponent : function()
    {
        this.monitorValid = true;

        this.accountStore = com.conjoon.groupware.email.AccountStore.getInstance();

         this.baseCls    = 'x-small-editor';
        this.labelWidth = 75;

        this.defaultType = 'textfield';
        this.title = com.conjoon.Gettext.gettext("Account name");
        this.defaults = {
            labelStyle : 'width:75px;font-size:11px',
            anchor: '100%'
         };

        this.nameField = new Ext.form.TextField({
            fieldLabel : com.conjoon.Gettext.gettext("Name"),
            allowBlank : false,
            validator  : this.validateAccountName.createDelegate(this),
            name       : 'name'
        });

        this.items = [
            new com.conjoon.groupware.util.FormIntro({
                style     : 'margin:10px 0 5px 0;',
                labelText : com.conjoon.Gettext.gettext("Account name"),
                text      : com.conjoon.Gettext.gettext("Specify a unique name for this account. This name will be used later on to identify this account. The name must not be already existing.")
            }),
            this.nameField
        ];

        com.conjoon.groupware.email.EmailAccountWizardAccountNameCard.superclass.initComponent.call(this);
    },

    validateAccountName : function(value)
    {
        value = value.trim().toLowerCase();

        if (value === "") {
            return false;
        } else {
            /**
             * @ext-bug 2.0.2 seems to look for any match
             */
            //var index = this.accountStore.find('name', value, 0, false, false);
            var recs = this.accountStore.getRange();
            for (var i = 0, len = recs.length; i < len; i++) {
                if (recs[i].get('name').toLowerCase() === value) {
                    return false;
                }
            }

            return true;
        }

        return true;
    }

});

com.conjoon.groupware.email.EmailAccountWizardFinishCard = Ext.extend(Ext.ux.Wiz.Card, {

    templates    : null,
    contentPanel : null,

    initComponent : function()
    {
        this.templates =  {
            master : new Ext.Template(
                '
'+
                    '
'+
                    '
'+com.conjoon.Gettext.gettext("Server type")+':	{protocol}
'+
                    '
'+com.conjoon.Gettext.gettext("Account name")+':	{name:htmlEncode}
'+
                    '
'+com.conjoon.Gettext.gettext("Your name")+':	{userName:htmlEncode}
'+
                    '
'+com.conjoon.Gettext.gettext("Email address")+':	{address:htmlEncode}
'+
                    '
'+com.conjoon.Gettext.gettext("Inbox host")+':	{serverInbox:htmlEncode}:{portInbox}
'+
                    '
'+com.conjoon.Gettext.gettext("Inbox user name")+':	{usernameInbox:htmlEncode}
'+
                    '
'+com.conjoon.Gettext.gettext("Inbox password")+':	{passwordInbox}
'+
                    '
'+com.conjoon.Gettext.gettext("Secure connection for inbox")+':	{inboxConnectionType}
'+
                    '
'+com.conjoon.Gettext.gettext("Outbox host")+':	{serverOutbox:htmlEncode}:{portOutbox}
'+
                    '
'+com.conjoon.Gettext.gettext("Outbox authentication")+':	{isOutboxAuth}
'+
                    '{auth_template}'+
                    '
'+
                '
'
            ),
            auth : new Ext.Template(
                '
'+com.conjoon.Gettext.gettext("Outbox user name")+':	{usernameOutbox:htmlEncode}
'+
                '
'+com.conjoon.Gettext.gettext("Outbox password")+':	{passwordOutbox}
'+
                '
'+com.conjoon.Gettext.gettext("Secure connection for outbox")+':	{outboxConnectionType}
'
            )
        };

        var ts = this.templates;

        for(var k in ts){
            ts[k].compile();
        }

        this.border = false;
        this.monitorValid = false;

        this.title = com.conjoon.Gettext.gettext("Confirm");

        this.contentPanel = new Ext.Panel({
            style : 'margin:0 0 0 20px'
        });

        this.items = [{
                border    : false,
                html      : "
"+com.conjoon.Gettext.gettext("The new account can now be created.
Please verify your submitted data and correct them if neccessary.")+"
",
                bodyStyle : 'background-color:#F6F6F6;margin:10px 0 10px 0'
            },
            this.contentPanel
        ];

        this.contentPanel.on('render', this.addContent, this, {single : true});

        com.conjoon.groupware.email.EmailAccountWizardFinishCard.superclass.initComponent.call(this);
    },

    addContent : function()
    {
        var ts = this.templates;

        var authTemplate = "";

        var items = this.ownerCt.items;

        var values = {};
        var formValues = {};
        for (var i = 0, len = items.length; i < len; i++) {
            formValues = items.get(i).form.getValues(false);
            for (var a in formValues) {
                values[a] = formValues[a];
            }
        }

        if (values.isOutboxAuth == 'on') {
            authTemplate = ts.auth.apply({
                usernameOutbox       : values.usernameOutbox,
                passwordOutbox       : "****",
                outboxConnectionType : values.outboxConnectionType == 'SSL'
                                        || values.outboxConnectionType == 'TLS'
                                      ? String.format(
                                            com.conjoon.Gettext.gettext("Uses {0}"),
                                            values.outboxConnectionType
                                        )
                                      : com.conjoon.Gettext.gettext("No")
            });
        }

        var html = ts.master.apply({
            portInbox     : values.portInbox,
            portOutbox    : values.portOutbox,
            protocol      : 'POP',//values.protocol,
            name          : values.name,
            userName      : values.userName,
            address       : values.address,
            serverInbox   : values.serverInbox,
            usernameInbox : values.usernameInbox,
            passwordInbox : "****",
            serverOutbox  : values.serverOutbox,
            isOutboxAuth  : values.isOutboxAuth == 'on'
                            ? com.conjoon.Gettext.gettext("Yes")
                            : com.conjoon.Gettext.gettext("No"),
            inboxConnectionType :  values.inboxConnectionType == 'SSL'
                                   || values.inboxConnectionType == 'TLS'
                                   ? String.format(
                                         com.conjoon.Gettext.gettext("Uses {0}"),
                                         values.inboxConnectionType
                                     )
                                   : com.conjoon.Gettext.gettext("No"),
            auth_template : authTemplate
        });

        this.contentPanel.el.update(html);

        this.on('show', this.addContent, this);
    }

});<|endoftext|>


<commit_before>export const hashRE = /#.*$/
export const extRE = /\.(md|html)$/
export const endingSlashRE = /\/$/
export const outboundRE = /^[a-z]+:/i

export function normalize (path) {
  return decodeURI(path)
    .replace(hashRE, '')
    .replace(extRE, '')
}

export function getHash (path) {
  const match = path.match(hashRE)
  if (match) {
    return match[0]
  }
}

export function isExternal (path) {
  return outboundRE.test(path)
}

export function isMailto (path) {
  return /^mailto:/.test(path)
}

export function isTel (path) {
  return /^tel:/.test(path)
}

export function ensureExt (path) {
  if (isExternal(path)) {
    return path
  }
  const hashMatch = path.match(hashRE)
  const hash = hashMatch ? hashMatch[0] : ''
  const normalized = normalize(path)

  if (endingSlashRE.test(normalized)) {
    return path
  }
  return normalized + '.html' + hash
}

export function isActive (route, path) {
  const routeHash = route.hash
  const linkHash = getHash(path)
  if (linkHash && routeHash !== linkHash) {
    return false
  }
  const routePath = normalize(route.path)
  const pagePath = normalize(path)
  return routePath === pagePath
}

export function resolvePage (pages, rawPath, base) {
  if (isExternal(rawPath)) {
    return {
      type: 'external',
      path: rawPath
    }
  }
  if (base) {
    rawPath = resolvePath(rawPath, base)
  }
  const path = normalize(rawPath)
  for (let i = 0; i < pages.length; i++) {
    if (normalize(pages[i].regularPath) === path) {
      return Object.assign({}, pages[i], {
        type: 'page',
        path: ensureExt(pages[i].path)
      })
    }
  }
  console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`)
  return {}
}

function resolvePath (relative, base, append) {
  const firstChar = relative.charAt(0)
  if (firstChar === '/') {
    return relative
  }

  if (firstChar === '?' || firstChar === '#') {
    return base + relative
  }

  const stack = base.split('/')

  // remove trailing segment if:
  // - not appending
  // - appending to trailing slash (last segment is empty)
  if (!append || !stack[stack.length - 1]) {
    stack.pop()
  }

  // resolve relative path
  const segments = relative.replace(/^\//, '').split('/')
  for (let i = 0; i < segments.length; i++) {
    const segment = segments[i]
    if (segment === '..') {
      stack.pop()
    } else if (segment !== '.') {
      stack.push(segment)
    }
  }

  // ensure leading slash
  if (stack[0] !== '') {
    stack.unshift('')
  }

  return stack.join('/')
}

/**
 * @param { Page } page
 * @param { string } regularPath
 * @param { SiteData } site
 * @param { string } localePath
 * @returns { SidebarGroup }
 */
export function resolveSidebarItems (page, regularPath, site, localePath) {
  const { pages, themeConfig } = site

  const localeConfig = localePath && themeConfig.locales
    ? themeConfig.locales[localePath] || themeConfig
    : themeConfig

  const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
  if (pageSidebarConfig === 'auto') {
    return resolveHeaders(page)
  }

  const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
  if (!sidebarConfig) {
    return []
  } else {
    const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
    if (config === 'auto') {
      return resolveHeaders(page)
    }
    return config
      ? config.map(item => resolveItem(item, pages, base))
      : []
  }
}

/**
 * @param { Page } page
 * @returns { SidebarGroup }
 */
function resolveHeaders (page) {
  const headers = groupHeaders(page.headers || [])
  return [{
    type: 'group',
    collapsable: false,
    title: page.title,
    path: null,
    children: headers.map(h => ({
      type: 'auto',
      title: h.title,
      basePath: page.path,
      path: page.path + '#' + h.slug,
      children: h.children || []
    }))
  }]
}

export function groupHeaders (headers) {
  // group h3s under h2
  headers = headers.map(h => Object.assign({}, h))
  let lastH2
  headers.forEach(h => {
    if (h.level === 2) {
      lastH2 = h
    } else if (lastH2) {
      (lastH2.children || (lastH2.children = [])).push(h)
    }
  })
  return headers.filter(h => h.level === 2)
}

export function resolveNavLinkItem (linkItem) {
  return Object.assign(linkItem, {
    type: linkItem.items && linkItem.items.length ? 'links' : 'link'
  })
}

/**
 * @param { Route } route
 * @param { Array<string|string[]> | Array<SidebarGroup> | [link: string]: SidebarConfig } config
 * @returns { base: string, config: SidebarConfig }
 */
export function resolveMatchingConfig (regularPath, config) {
  if (Array.isArray(config)) {
    return {
      base: '/',
      config: config
    }
  }
  for (const base in config) {
    if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) {
      return {
        base,
        config: config[base]
      }
    }
  }
  return {}
}

function ensureEndingSlash (path) {
  return /(\.html|\/)$/.test(path)
    ? path
    : path + '/'
}

function resolveItem (item, pages, base, groupDepth = 1) {
  if (typeof item === 'string') {
    return resolvePage(pages, item, base)
  } else if (Array.isArray(item)) {
    return Object.assign(resolvePage(pages, item[0], base), {
      title: item[1]
    })
  } else {
    if (groupDepth > 3) {
      console.error(
        '[vuepress] detected a too deep nested sidebar group.'
      )
    }
    const children = item.children || []
    if (children.length === 0 && item.path) {
      return Object.assign(resolvePage(pages, item.path, base), {
        title: item.title
      })
    }
    return {
      type: 'group',
      path: item.path,
      title: item.title,
      sidebarDepth: item.sidebarDepth,
      initialOpenGroupIndex: item.initialOpenGroupIndex,
      children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)),
      collapsable: item.collapsable !== false
    }
  }
}

// 类型判断
export function type (o) {
  const s = Object.prototype.toString.call(o)
  return s.match(/\[object (.*?)\]/)[1].toLowerCase()
}

// 日期格式化(只获取年月日)
export function dateFormat (date) {
  if (!(date instanceof Date)) {
    date = new Date(date)
  }
  return `${date.getUTCFullYear()}-${zero(date.getUTCMonth() + 1)}-${zero(date.getUTCDate())}`
}

// 小于10补0
export function zero (d) {
  return d.toString().padStart(2, '0')
}

// 获取时间的时间戳
export function getTimeNum (post) {
  let dateStr = post.frontmatter.date || post.lastUpdated || new Date()
  let date = new Date(dateStr)
  if (date == "Invalid Date" && dateStr) { // 修复new Date()在Safari下出现Invalid Date的问题
    date = new Date(dateStr?.replace(/-/g, '/'))
  }
  return date.getTime()
}

// 比对时间
export function compareDate (a, b) {
  return getTimeNum(b) - getTimeNum(a)
}

// 将特殊符号编码（应用于url）
export function encodeUrl (str) {
  str = str + ''
  str = str?.replace(/ |((?=[\x21-\x7e]+)[^A-Za-z0-9])/g, '-')
  return str
}
<commit_msg>Update index.js<commit_after>export const hashRE = /#.*$/
export const extRE = /\.(md|html)$/
export const endingSlashRE = /\/$/
export const outboundRE = /^[a-z]+:/i

export function normalize (path) {
  return decodeURI(path)
    .replace(hashRE, '')
    .replace(extRE, '')
}

export function getHash (path) {
  const match = path.match(hashRE)
  if (match) {
    return match[0]
  }
}

export function isExternal (path) {
  return outboundRE.test(path)
}

export function isMailto (path) {
  return /^mailto:/.test(path)
}

export function isTel (path) {
  return /^tel:/.test(path)
}

export function ensureExt (path) {
  if (isExternal(path)) {
    return path
  }
  const hashMatch = path.match(hashRE)
  const hash = hashMatch ? hashMatch[0] : ''
  const normalized = normalize(path)

  if (endingSlashRE.test(normalized)) {
    return path
  }
  return normalized + '.html' + hash
}

export function isActive (route, path) {
  const routeHash = route.hash
  const linkHash = getHash(path)
  if (linkHash && routeHash !== linkHash) {
    return false
  }
  const routePath = normalize(route.path)
  const pagePath = normalize(path)
  return routePath === pagePath
}

export function resolvePage (pages, rawPath, base) {
  if (isExternal(rawPath)) {
    return {
      type: 'external',
      path: rawPath
    }
  }
  if (base) {
    rawPath = resolvePath(rawPath, base)
  }
  const path = normalize(rawPath)
  for (let i = 0; i < pages.length; i++) {
    if (normalize(pages[i].regularPath) === path) {
      return Object.assign({}, pages[i], {
        type: 'page',
        path: ensureExt(pages[i].path)
      })
    }
  }
  console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`)
  return {}
}

function resolvePath (relative, base, append) {
  const firstChar = relative.charAt(0)
  if (firstChar === '/') {
    return relative
  }

  if (firstChar === '?' || firstChar === '#') {
    return base + relative
  }

  const stack = base.split('/')

  // remove trailing segment if:
  // - not appending
  // - appending to trailing slash (last segment is empty)
  if (!append || !stack[stack.length - 1]) {
    stack.pop()
  }

  // resolve relative path
  const segments = relative.replace(/^\//, '').split('/')
  for (let i = 0; i < segments.length; i++) {
    const segment = segments[i]
    if (segment === '..') {
      stack.pop()
    } else if (segment !== '.') {
      stack.push(segment)
    }
  }

  // ensure leading slash
  if (stack[0] !== '') {
    stack.unshift('')
  }

  return stack.join('/')
}

/**
 * @param { Page } page
 * @param { string } regularPath
 * @param { SiteData } site
 * @param { string } localePath
 * @returns { SidebarGroup }
 */
export function resolveSidebarItems (page, regularPath, site, localePath) {
  const { pages, themeConfig } = site

  const localeConfig = localePath && themeConfig.locales
    ? themeConfig.locales[localePath] || themeConfig
    : themeConfig

  const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
  if (pageSidebarConfig === 'auto') {
    return resolveHeaders(page)
  }

  const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
  if (!sidebarConfig) {
    return []
  } else {
    const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
    if (config === 'auto') {
      return resolveHeaders(page)
    }
    return config
      ? config.map(item => resolveItem(item, pages, base))
      : []
  }
}

/**
 * @param { Page } page
 * @returns { SidebarGroup }
 */
function resolveHeaders (page) {
  const headers = groupHeaders(page.headers || [])
  return [{
    type: 'group',
    collapsable: false,
    title: page.title,
    path: null,
    children: headers.map(h => ({
      type: 'auto',
      title: h.title,
      basePath: page.path,
      path: page.path + '#' + h.slug,
      children: h.children || []
    }))
  }]
}

export function groupHeaders (headers) {
  // group h3s under h2
  headers = headers.map(h => Object.assign({}, h))
  let lastH2
  headers.forEach(h => {
    if (h.level === 2) {
      lastH2 = h
    } else if (lastH2) {
      (lastH2.children || (lastH2.children = [])).push(h)
    }
  })
  return headers.filter(h => h.level === 2)
}

export function resolveNavLinkItem (linkItem) {
  return Object.assign(linkItem, {
    type: linkItem.items && linkItem.items.length ? 'links' : 'link'
  })
}

/**
 * @param { Route } route
 * @param { Array<string|string[]> | Array<SidebarGroup> | [link: string]: SidebarConfig } config
 * @returns { base: string, config: SidebarConfig }
 */
export function resolveMatchingConfig (regularPath, config) {
  if (Array.isArray(config)) {
    return {
      base: '/',
      config: config
    }
  }
  for (const base in config) {
    if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) {
      return {
        base,
        config: config[base]
      }
    }
  }
  return {}
}

function ensureEndingSlash (path) {
  return /(\.html|\/)$/.test(path)
    ? path
    : path + '/'
}

function resolveItem (item, pages, base, groupDepth = 1) {
  if (typeof item === 'string') {
    return resolvePage(pages, item, base)
  } else if (Array.isArray(item)) {
    return Object.assign(resolvePage(pages, item[0], base), {
      title: item[1]
    })
  } else {
    if (groupDepth > 3) {
      console.error(
        '[vuepress] detected a too deep nested sidebar group.'
      )
    }
    const children = item.children || []
    if (children.length === 0 && item.path) {
      return Object.assign(resolvePage(pages, item.path, base), {
        title: item.title
      })
    }
    return {
      type: 'group',
      path: item.path,
      title: item.title,
      sidebarDepth: item.sidebarDepth,
      initialOpenGroupIndex: item.initialOpenGroupIndex,
      children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)),
      collapsable: item.collapsable !== false
    }
  }
}

// 类型判断
export function type (o) {
  const s = Object.prototype.toString.call(o)
  return s.match(/\[object (.*?)\]/)[1].toLowerCase()
}

// 日期格式化(只获取年月日)
export function dateFormat (date) {
  if (!(date instanceof Date)) {
    date = new Date(date)
  }
  return `${date.getUTCFullYear()}-${zero(date.getUTCMonth() + 1)}-${zero(date.getUTCDate())}`
}

// 小于10补0
export function zero (d) {
  return d.toString().padStart(2, '0')
}

// 获取时间的时间戳
export function getTimeNum (post) {
  let dateStr = post.frontmatter.date || post.lastUpdated || new Date()
  let date = new Date(dateStr)
  if (date == "Invalid Date" && dateStr) { // 修复new Date()在Safari下出现Invalid Date的问题
    date = new Date(dateStr.replace(/-/g, '/'))
  }
  return date.getTime()
}

// 比对时间
export function compareDate (a, b) {
  return getTimeNum(b) - getTimeNum(a)
}

// 将特殊符号编码（应用于url）
export function encodeUrl (str) {
  str = str + ''
  str = str.replace(/ |((?=[\x21-\x7e]+)[^A-Za-z0-9])/g, '-')
  return str
}
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash')
  , iob = require('./iob')()
  , moment = require('moment');

function init() {

  function cob() {
    return cob;
  }

  cob.label = 'Carbs-on-Board';
  cob.pluginType = 'pill-minor';

  cob.setProperties = function setProperties(sbx) {
    sbx.offerProperty('cob', function setCOB ( ) {
      return cob.cobTotal(sbx.data.treatments, sbx.data.profile, sbx.time);
    });
  };

  cob.cobTotal = function cobTotal(treatments, profile, time) {

    if (!profile || !profile.hasData()) {
      console.warn('For the COB plugin to function you need a treatment profile');
      return {};
    }

    if (!profile.getSensitivity(time) || !profile.getCarbRatio(time)) {
      console.warn('For the CPB plugin to function your treatment profile must have both sens and carbratio fields');
      return {};
    }

    var liverSensRatio = 1;
    var totalCOB = 0;
    var lastCarbs = null;
    if (!treatments) return {};
    if (typeof time === 'undefined') {
      time = new Date();
    }

    var isDecaying = 0;
    var lastDecayedBy = new Date('1/1/1970');

    _.forEach(treatments, function eachTreatment(treatment) {
      if (treatment.carbs && treatment.created_at < time) {
        lastCarbs = treatment;
        var cCalc = cob.cobCalc(treatment, profile, lastDecayedBy, time);
        console.log(cCalc);
        var decaysin_hr = (cCalc.decayedBy - time) / 1000 / 60 / 60;
        if (decaysin_hr > -10) {
          var actStart = iob.calcTotal(treatments, profile, lastDecayedBy).activity;
          var actEnd = iob.calcTotal(treatments, profile, cCalc.decayedBy).activity;
          var avgActivity = (actStart + actEnd) / 2;
          var delayedCarbs = avgActivity * liverSensRatio * profile.getSensitivity(treatment.created_at) / profile.getCarbRatio(treatment.created_at);
          var delayMinutes = Math.round(delayedCarbs / profile.getCarbAbsorptionRate(treatment.created_at) * 60);
          if (delayMinutes > 0) {
            cCalc.decayedBy.setMinutes(cCalc.decayedBy.getMinutes() + delayMinutes);
            decaysin_hr = (cCalc.decayedBy - time) / 1000 / 60 / 60;
          }
        }

        if (cCalc) {
          lastDecayedBy = cCalc.decayedBy;
        }

        if (decaysin_hr > 0) {
          //console.info('Adding ' + delayMinutes + ' minutes to decay of ' + treatment.carbs + 'g bolus at ' + treatment.created_at);
          totalCOB += Math.min(Number(treatment.carbs), decaysin_hr * profile.getCarbAbsorptionRate(treatment.created_at));
          //console.log("cob:", Math.min(cCalc.initialCarbs, decaysin_hr * profile.getCarbAbsorptionRate(treatment.created_at)),cCalc.initialCarbs,decaysin_hr,profile.getCarbAbsorptionRate(treatment.created_at));
          isDecaying = cCalc.isDecaying;
        } else {
          totalCOB = 0;
        }

      }
    });

    var rawCarbImpact = isDecaying * profile.getSensitivity(time) / profile.getCarbRatio(time) * profile.getCarbAbsorptionRate(time) / 60;

    return {
      decayedBy: lastDecayedBy,
      isDecaying: isDecaying,
      carbs_hr: profile.getCarbAbsorptionRate(time),
      rawCarbImpact: rawCarbImpact,
      cob: totalCOB,
      lastCarbs: lastCarbs
    };
  };

  cob.carbImpact = function carbImpact(rawCarbImpact, insulinImpact) {
    var liverSensRatio = 1.0;
    var liverCarbImpactMax = 0.7;
    var liverCarbImpact = Math.min(liverCarbImpactMax, liverSensRatio * insulinImpact);
    //var liverCarbImpact = liverSensRatio*insulinImpact;
    var netCarbImpact = Math.max(0, rawCarbImpact - liverCarbImpact);
    var totalImpact = netCarbImpact - insulinImpact;
    return {
      netCarbImpact: netCarbImpact,
      totalImpact: totalImpact
    }
  };

  cob.cobCalc = function cobCalc(treatment, profile, lastDecayedBy, time) {

    var delay = 20;
    var isDecaying = 0;
    var initialCarbs;

    if (treatment.carbs) {
      var carbTime = new Date(treatment.created_at);

      var carbs_hr = profile.getCarbAbsorptionRate(treatment.created_at);
      var carbs_min = carbs_hr / 60;

      var decayedBy = new Date(carbTime);
      var minutesleft = (lastDecayedBy - carbTime) / 1000 / 60;
      decayedBy.setMinutes(decayedBy.getMinutes() + Math.max(delay, minutesleft) + treatment.carbs / carbs_min);
      if (delay > minutesleft) {
        initialCarbs = parseInt(treatment.carbs);
      }
      else {
        initialCarbs = parseInt(treatment.carbs) + minutesleft * carbs_min;
      }
      var startDecay = new Date(carbTime);
      startDecay.setMinutes(carbTime.getMinutes() + delay);
      if (time < lastDecayedBy || time > startDecay) {
        isDecaying = 1;
      }
      else {
        isDecaying = 0;
      }
      return {
        initialCarbs: initialCarbs,
        decayedBy: decayedBy,
        isDecaying: isDecaying,
        carbTime: carbTime
      };
    }
    else {
      return '';
    }
  };

  cob.updateVisualisation = function updateVisualisation(sbx) {

    var prop = sbx.properties.cob.cob;
    if (prop == undefined) return;

    var displayCob = Math.round(prop * 10) / 10;

    var info = null;
    if (prop.lastCarbs) {
      var when = moment(new Date(prop.lastCarbs.created_at)).format('lll');
      var amount = prop.lastCarbs.carbs + 'g';
      info = [{label: 'Last Carbs', value: amount + ' @ ' + when }]
    }

    sbx.pluginBase.updatePillText(sbx, displayCob + " g", 'COB', info);
  };

  return cob();

}

module.exports = init;
<commit_msg>Removing a logging line<commit_after>'use strict';

var _ = require('lodash')
  , iob = require('./iob')()
  , moment = require('moment');

function init() {

  function cob() {
    return cob;
  }

  cob.label = 'Carbs-on-Board';
  cob.pluginType = 'pill-minor';

  cob.setProperties = function setProperties(sbx) {
    sbx.offerProperty('cob', function setCOB ( ) {
      return cob.cobTotal(sbx.data.treatments, sbx.data.profile, sbx.time);
    });
  };

  cob.cobTotal = function cobTotal(treatments, profile, time) {

    if (!profile || !profile.hasData()) {
      console.warn('For the COB plugin to function you need a treatment profile');
      return {};
    }

    if (!profile.getSensitivity(time) || !profile.getCarbRatio(time)) {
      console.warn('For the CPB plugin to function your treatment profile must have both sens and carbratio fields');
      return {};
    }

    var liverSensRatio = 1;
    var totalCOB = 0;
    var lastCarbs = null;
    if (!treatments) return {};
    if (typeof time === 'undefined') {
      time = new Date();
    }

    var isDecaying = 0;
    var lastDecayedBy = new Date('1/1/1970');

    _.forEach(treatments, function eachTreatment(treatment) {
      if (treatment.carbs && treatment.created_at < time) {
        lastCarbs = treatment;
        var cCalc = cob.cobCalc(treatment, profile, lastDecayedBy, time);
        var decaysin_hr = (cCalc.decayedBy - time) / 1000 / 60 / 60;
        if (decaysin_hr > -10) {
          var actStart = iob.calcTotal(treatments, profile, lastDecayedBy).activity;
          var actEnd = iob.calcTotal(treatments, profile, cCalc.decayedBy).activity;
          var avgActivity = (actStart + actEnd) / 2;
          var delayedCarbs = avgActivity * liverSensRatio * profile.getSensitivity(treatment.created_at) / profile.getCarbRatio(treatment.created_at);
          var delayMinutes = Math.round(delayedCarbs / profile.getCarbAbsorptionRate(treatment.created_at) * 60);
          if (delayMinutes > 0) {
            cCalc.decayedBy.setMinutes(cCalc.decayedBy.getMinutes() + delayMinutes);
            decaysin_hr = (cCalc.decayedBy - time) / 1000 / 60 / 60;
          }
        }

        if (cCalc) {
          lastDecayedBy = cCalc.decayedBy;
        }

        if (decaysin_hr > 0) {
          //console.info('Adding ' + delayMinutes + ' minutes to decay of ' + treatment.carbs + 'g bolus at ' + treatment.created_at);
          totalCOB += Math.min(Number(treatment.carbs), decaysin_hr * profile.getCarbAbsorptionRate(treatment.created_at));
          //console.log("cob:", Math.min(cCalc.initialCarbs, decaysin_hr * profile.getCarbAbsorptionRate(treatment.created_at)),cCalc.initialCarbs,decaysin_hr,profile.getCarbAbsorptionRate(treatment.created_at));
          isDecaying = cCalc.isDecaying;
        } else {
          totalCOB = 0;
        }

      }
    });

    var rawCarbImpact = isDecaying * profile.getSensitivity(time) / profile.getCarbRatio(time) * profile.getCarbAbsorptionRate(time) / 60;

    return {
      decayedBy: lastDecayedBy,
      isDecaying: isDecaying,
      carbs_hr: profile.getCarbAbsorptionRate(time),
      rawCarbImpact: rawCarbImpact,
      cob: totalCOB,
      lastCarbs: lastCarbs
    };
  };

  cob.carbImpact = function carbImpact(rawCarbImpact, insulinImpact) {
    var liverSensRatio = 1.0;
    var liverCarbImpactMax = 0.7;
    var liverCarbImpact = Math.min(liverCarbImpactMax, liverSensRatio * insulinImpact);
    //var liverCarbImpact = liverSensRatio*insulinImpact;
    var netCarbImpact = Math.max(0, rawCarbImpact - liverCarbImpact);
    var totalImpact = netCarbImpact - insulinImpact;
    return {
      netCarbImpact: netCarbImpact,
      totalImpact: totalImpact
    }
  };

  cob.cobCalc = function cobCalc(treatment, profile, lastDecayedBy, time) {

    var delay = 20;
    var isDecaying = 0;
    var initialCarbs;

    if (treatment.carbs) {
      var carbTime = new Date(treatment.created_at);

      var carbs_hr = profile.getCarbAbsorptionRate(treatment.created_at);
      var carbs_min = carbs_hr / 60;

      var decayedBy = new Date(carbTime);
      var minutesleft = (lastDecayedBy - carbTime) / 1000 / 60;
      decayedBy.setMinutes(decayedBy.getMinutes() + Math.max(delay, minutesleft) + treatment.carbs / carbs_min);
      if (delay > minutesleft) {
        initialCarbs = parseInt(treatment.carbs);
      }
      else {
        initialCarbs = parseInt(treatment.carbs) + minutesleft * carbs_min;
      }
      var startDecay = new Date(carbTime);
      startDecay.setMinutes(carbTime.getMinutes() + delay);
      if (time < lastDecayedBy || time > startDecay) {
        isDecaying = 1;
      }
      else {
        isDecaying = 0;
      }
      return {
        initialCarbs: initialCarbs,
        decayedBy: decayedBy,
        isDecaying: isDecaying,
        carbTime: carbTime
      };
    }
    else {
      return '';
    }
  };

  cob.updateVisualisation = function updateVisualisation(sbx) {

    var prop = sbx.properties.cob.cob;
    if (prop == undefined) return;

    var displayCob = Math.round(prop * 10) / 10;

    var info = null;
    if (prop.lastCarbs) {
      var when = moment(new Date(prop.lastCarbs.created_at)).format('lll');
      var amount = prop.lastCarbs.carbs + 'g';
      info = [{label: 'Last Carbs', value: amount + ' @ ' + when }]
    }

    sbx.pluginBase.updatePillText(sbx, displayCob + " g", 'COB', info);
  };

  return cob();

}

module.exports = init;
<|endoftext|>