<commit_before>var _ = require('underscore');
var Backbone = require('backbone');
var LegendManager = require('./legend-manager');
var linkLayerInfowindow = require('./link-layer-infowindow');
var linkLayerTooltip = require('./link-layer-tooltip');
var layerTypesAndKinds = require('../data/layer-types-and-kinds');
var Notifier = require('../components/notifier/notifier');
var checkAndBuildOpts = require('../helpers/required-opts');
var NotificationErrorMessageHandler = require('../editor/layers/notification-error-message-handler');
var basemapProvidersAndCategories = require('../data/basemap-providers-and-categories');

var REQUIRED_OPTS = [
  'analysisDefinitionNodesCollection',
  'editFeatureOverlay',
  'layerDefinitionsCollection',
  'legendDefinitionsCollection',
  'diDashboardHelpers'
];

var LAYER_TYPE_TO_LAYER_CREATE_METHOD = {
  'cartodb': 'createCartoDBLayer',
  'gmapsbase': 'createGMapsBaseLayer',
  'plain': 'createPlainLayer',
  'tiled': 'createTileLayer',
  'torque': 'createTorqueLayer',
  'wms': 'createWMSLayer',
  'raster_tileo': 'createRasterTileoLayer'
};

var CARTODBJS_TO_CARTODB_ATTRIBUTE_MAPPINGS = {
  'layer_name': ['table_name_alias', 'table_name']
};

var BLACKLISTED_LAYER_DEFINITION_ATTRS = {
  'all': [ 'letter', 'kind' ],
  'Tiled': [ 'category', 'selected', 'highlighted' ],
  'CartoDB': [ 'color', 'letter' ],
  'torque': [ 'color', 'letter' ]
};

/**
 *  Only manage **LAYER** actions between Deep-Insights (CARTO.js) and Builder
 *
 */

var LayersIntegration = {
  track: function (options) {
    checkAndBuildOpts(options, REQUIRED_OPTS, this);

    this._visMap = this._diDashboardHelpers.visMap();

    this._layerDefinitionsCollection.each(this._linkLayerErrors, this);
    this._layerDefinitionsCollection.on('add', this._onLayerDefinitionAdded, this);
    this._layerDefinitionsCollection.on('sync', this._onLayerDefinitionSynced, this);
    this._layerDefinitionsCollection.on('change', this._onLayerDefinitionChanged, this);
    this._layerDefinitionsCollection.on('remove', this._onLayerDefinitionRemoved, this);
    this._layerDefinitionsCollection.on('layerMoved', this._onLayerDefinitionMoved, this);
    this._layerDefinitionsCollection.on('baseLayerChanged', this._onBaseLayerChanged, this);

    this._layerDefinitionsCollection.each(function (layerDefModel) {
      LegendManager.track(layerDefModel);

      linkLayerInfowindow(layerDefModel, this._visMap);
      linkLayerTooltip(layerDefModel, this._visMap);

      if (layerDefModel.has('source')) {
        this._resetStylesIfNoneApplied(layerDefModel);
      }
    }, this);

    // In order to sync layer selector and layer visibility
    this._diDashboardHelpers.getLayers().on('change:visible', function (layer, visible) {
      var layerDefModel = this._layerDefinitionsCollection.findWhere({id: layer.id});
      if (layerDefModel) {
        if (layerDefModel.get('visible') !== visible) {
          layerDefModel.save({visible: visible});
        }
      }
    }, this);

    return this;
  },

  _onLayerDefinitionRemoved: function (m) {
    if (!m.isNew()) {
      var layer = this._diDashboardHelpers.getLayer(m.id);
      layer && layer.remove();
    }
  },

  _onLayerDefinitionMoved: function (m, from, to) {
    this._diDashboardHelpers.moveCartoDBLayer(from, to);
  },

  _createLayer: function (layerDefModel, options) {
    options = options || {};
    var attrs = JSON.parse(JSON.stringify(layerDefModel.attributes)); // deep clone
    attrs = this._adaptAttrsToCDBjs(layerDefModel.get('type'), attrs);

    // create the legends for the new layer
    var legends = this._legendDefinitionsCollection.findByLayerDefModel(layerDefModel);
    if (legends.length > 0) {
      attrs.legends = _.map(legends, function (legend) {
        return legend.toJSON();
      });
    }
    attrs.type = (attrs.layer_name.indexOf('_raster') >= 0) ? 'raster_tileo' : attrs.type;
    var createMethodName = LAYER_TYPE_TO_LAYER_CREATE_METHOD[attrs.type.toLowerCase()];
    if (!createMethodName) throw new Error('no create method name found for type ' + attrs.type);

    if (attrs.source) {
      // Make sure the analysis is created first
      var nodeDefModel = this._analysisDefinitionNodesCollection.get(attrs.source);
      // Dependency with another integration
      this.trigger('onLayerCreation', nodeDefModel);
    }

    var layerPosition = this._layerDefinitionsCollection.indexOf(layerDefModel);
    this._visMap[createMethodName](attrs, _.extend({
      at: layerPosition
    }, options));

    linkLayerInfowindow(layerDefModel, this._visMap);
    linkLayerTooltip(layerDefModel, this._visMap);
    LegendManager.track(layerDefModel);

    this._linkLayerErrors(layerDefModel);
  },

  _linkLayerErrors: function (m) {
    var layer = this._diDashboardHelpers.getLayer(m.id);
    if (layer) {
      if (layer.get('error')) {
        this._setLayerError(m, layer.get('error'));
      }
      layer.on('change:error', function (model, cdbError) {
        this._setLayerError(m, cdbError);
      }, this);
    }
  },

  _setLayerError: function (layerDefinitionModel, cdbError) {
    // Check error is not thrown because of RASTER + the_geom_webmercator
    if (!!(layerDefinitionModel.attributes.table_name.indexOf('raster') > 0) && !!(cdbError.message.indexOf('column "the_geom_webmercator" does not exist') > 0)) {
      return;
    }
    var notification = Notifier.getNotification(layerDefinitionModel.id);
    var mainErrorMessage = layerDefinitionModel.getName() + ': ' + (cdbError && cdbError.message);

    if (!cdbError) {
      layerDefinitionModel.unset('error');
      notification && Notifier.removeNotification(notification);
      return;
    }

    var errorMessage = NotificationErrorMessageHandler.extractError(mainErrorMessage);

    if (notification) {
      notification.update({
        status: errorMessage.type,
        info: errorMessage.message
      });
    } else {
      Notifier.addNotification({
        id: layerDefinitionModel.id,
        status: errorMessage.type,
        closable: true,
        button: false,
        info: errorMessage.message
      });
    }

    if (cdbError.type === 'turbo-carto') {
      var line;
      try {
        line = cdbError.context.source.start.line;
      } catch (error) {}

      layerDefinitionModel.set('error', {
        type: cdbError.type,
        line: line,
        message: cdbError.message
      });
    } else if (errorMessage) {
      layerDefinitionModel.set('error', {
        type: errorMessage.type,
        message: errorMessage.message
      });
    }
  },

  _onLayerDefinitionAdded: function (m, c, opts) {
    // Base and labels layers are synced in a separate method
    if (!layerTypesAndKinds.isTypeDataLayer(m.get('type'))) {
      return;
    }

    // If added but not yet saved, postpone the creation until persisted (see sync listener)
    if (!m.isNew()) {
      if (!this._diDashboardHelpers.getLayer(m.id)) {
        this._createLayer(m);
      } else {
        // we need to sync model positions
        this._tryUpdateLayerPosition(m);
      }
    }
  },

  _tryUpdateLayerPosition: function (m) {
    var builderPosition = this._layerDefinitionsCollection.indexOf(m);
    var cdbLayer = this._diDashboardHelpers.getLayer(m.id);
    var cdbPosition;

    if (cdbLayer) {
      cdbPosition = this._diDashboardHelpers.getLayers().indexOf(cdbLayer);
    }

    var indexChanges = m.isDataLayer() && cdbPosition > 0 && builderPosition > 0 && builderPosition !== cdbPosition;

    if (indexChanges) {
      this._diDashboardHelpers.moveCartoDBLayer(cdbPosition, builderPosition);
    }
  },

  _onLayerDefinitionSynced: function (m) {
    // Base and labels layers are synced in a separate method
    if (!layerTypesAndKinds.isTypeDataLayer(m.get('type'))) {
      return;
    }

    if (!this._diDashboardHelpers.getLayer(m.id)) {
      this._createLayer(m);
    }
  },

  _onLayerDefinitionChanged: function (layerDefinitionModel, changedAttributes) {
    var attrs = layerDefinitionModel.changedAttributes();
    var attrsNames = _.keys(attrs);

    // Base and labels layers are synced in a separate method
    if (!layerTypesAndKinds.isTypeDataLayer(layerDefinitionModel.get('type'))) {
      return;
    }

    // return if only the 'error' attribute has changed (no need to sync anything)
    if (attrsNames.length === 1 && attrsNames[0] === 'error') {
      return;
    }

    var layer = this._diDashboardHelpers.getLayer(layerDefinitionModel.id);
    if (!layerDefinitionModel.isNew()) {
      if (!layer) {
        this._createLayer(layerDefinitionModel);
        return;
      }

      if (attrs.type) {
        layer.remove();
        this._createLayer(layerDefinitionModel);
      } else {
        if (layerDefinitionModel.get('source') && !layer.get('source')) {
          attrs.source = layerDefinitionModel.get('source');
        }
        attrs = this._adaptAttrsToCDBjs(layerDefinitionModel.get('type'), attrs);
        layer.update(attrs);
      }
      // Dependency with widgets-integration
      this.trigger('onLayerChanged', layerDefinitionModel);
    }
  },

  _onBaseLayerChanged: function () {
    var baseLayerDefinition = this._layerDefinitionsCollection.getBaseLayer();
    var newBaseLayerAttrs = baseLayerDefinition.changedAttributes();

    var newBaseLayerType = baseLayerDefinition.get('type');
    var newMapProvider = basemapProvidersAndCategories.getProvider(newBaseLayerType);
    var mapProviderChanged = false;
    if (baseLayerDefinition.hasChanged('type')) {
      var previousBaseLayerType = baseLayerDefinition.previous('type');
      var previousMapProvider = basemapProvidersAndCategories.getProvider(previousBaseLayerType);
      mapProviderChanged = previousMapProvider !== newMapProvider;
    }

    // If the map provider has changed (eg: Leaflet -> Google Maps), we add/update/remove base and
    // labels layers silently so that CartoDB.js doesn't pick up those changes and tries to add/update/remove
    // layers until the new map provider has been set
    var handleLayersSilently = mapProviderChanged;

    // Base layer
    var cdbjsLayer = this._diDashboardHelpers.getLayer(baseLayerDefinition.id);

    // If the type of base layer has changed. eg: Tiled -> Plain
    if (newBaseLayerAttrs.type) {
      cdbjsLayer.remove({ silent: handleLayersSilently });
      this._createLayer(baseLayerDefinition, { silent: handleLayersSilently });
    } else {
      cdbjsLayer.update(this._adaptAttrsToCDBjs(baseLayerDefinition.get('type'), newBaseLayerAttrs), {
        silent: handleLayersSilently
      });
    }

    // Labels layer
    var labelsLayerDefinition = this._layerDefinitionsCollection.getLabelsLayer();
    var cdbjsTopLayer = this._diDashboardHelpers.getLayers().last();
    var cdbjsHasLabelsLayer = cdbjsTopLayer.get('type') === 'Tiled';

    if (labelsLayerDefinition) {
      if (cdbjsHasLabelsLayer) {
        var changedAttrs = labelsLayerDefinition.changedAttributes();
        if (changedAttrs) {
          cdbjsTopLayer.update(this._adaptAttrsToCDBjs(labelsLayerDefinition.get('type'), changedAttrs), {
            silent: handleLayersSilently
          });
        }
      } else {
        this._createLayer(labelsLayerDefinition, { silent: handleLayersSilently });
      }
    } else if (cdbjsHasLabelsLayer) {
      cdbjsTopLayer.remove({ silent: handleLayersSilently });
    }

    // Map provider
    this._visMap.set('provider', newMapProvider);

    if (handleLayersSilently) {
      // Reload map if everything (previously) was done silently
      this._diDashboardHelpers.reloadMap();
    }

    // Render again the edit-feature-overlay, in order to
    // decide if delegate or not events
    this._editFeatureOverlay.render();

    // Dependency with map-integration class
    this.trigger('onBaseLayerChanged');
  },

  _resetStylesIfNoneApplied: function (layerDefModel) {
    var nodeDefModel = layerDefModel.getAnalysisDefinitionNodeModel();
    var analysisCollection = this._diDashboardHelpers.getAnalyses();
    var nodeModel = analysisCollection && analysisCollection.findNodeById(layerDefModel.get('source'));
    var isAnalysisNode = nodeModel && nodeModel.get('type') !== 'source';
    var isDone = nodeModel && nodeModel.isDone();
    var queryGeometryModel = nodeDefModel && nodeDefModel.queryGeometryModel;
    var styleModel = layerDefModel.styleModel;

    if (isAnalysisNode && styleModel.hasNoneStyles() && isDone) {
      var simpleGeom = queryGeometryModel.get('simple_geom');

      var applyDefaultStyles = function () {
        simpleGeom = queryGeometryModel.get('simple_geom');
        styleModel.setDefaultPropertiesByType('simple', simpleGeom);
      };

      if (!simpleGeom) {
        queryGeometryModel.once('change:simple_geom', applyDefaultStyles, this);
        queryGeometryModel.fetch();
      } else {
        applyDefaultStyles();
      }
    }
  },

  _adaptAttrsToCDBjs: function (layerType, attrs) {
    attrs = _.omit(attrs, BLACKLISTED_LAYER_DEFINITION_ATTRS['all'], BLACKLISTED_LAYER_DEFINITION_ATTRS[layerType]);
    _.each(CARTODBJS_TO_CARTODB_ATTRIBUTE_MAPPINGS, function (cdbAttrs, cdbjsAttr) {
      _.each(cdbAttrs, function (cdbAttr) {
        if (attrs[cdbAttr] && !attrs[cdbjsAttr]) {
          attrs[cdbjsAttr] = attrs[cdbAttr];
        }
      });
    });

    return attrs;
  }
};

_.extend(LayersIntegration, Backbone.Events);

module.exports = LayersIntegration;
<commit_msg>FIX: check we are handling a layer<commit_after>var _ = require('underscore');
var Backbone = require('backbone');
var LegendManager = require('./legend-manager');
var linkLayerInfowindow = require('./link-layer-infowindow');
var linkLayerTooltip = require('./link-layer-tooltip');
var layerTypesAndKinds = require('../data/layer-types-and-kinds');
var Notifier = require('../components/notifier/notifier');
var checkAndBuildOpts = require('../helpers/required-opts');
var NotificationErrorMessageHandler = require('../editor/layers/notification-error-message-handler');
var basemapProvidersAndCategories = require('../data/basemap-providers-and-categories');

var REQUIRED_OPTS = [
  'analysisDefinitionNodesCollection',
  'editFeatureOverlay',
  'layerDefinitionsCollection',
  'legendDefinitionsCollection',
  'diDashboardHelpers'
];

var LAYER_TYPE_TO_LAYER_CREATE_METHOD = {
  'cartodb': 'createCartoDBLayer',
  'gmapsbase': 'createGMapsBaseLayer',
  'plain': 'createPlainLayer',
  'tiled': 'createTileLayer',
  'torque': 'createTorqueLayer',
  'wms': 'createWMSLayer',
  'raster_tileo': 'createRasterTileoLayer'
};

var CARTODBJS_TO_CARTODB_ATTRIBUTE_MAPPINGS = {
  'layer_name': ['table_name_alias', 'table_name']
};

var BLACKLISTED_LAYER_DEFINITION_ATTRS = {
  'all': [ 'letter', 'kind' ],
  'Tiled': [ 'category', 'selected', 'highlighted' ],
  'CartoDB': [ 'color', 'letter' ],
  'torque': [ 'color', 'letter' ]
};

/**
 *  Only manage **LAYER** actions between Deep-Insights (CARTO.js) and Builder
 *
 */

var LayersIntegration = {
  track: function (options) {
    checkAndBuildOpts(options, REQUIRED_OPTS, this);

    this._visMap = this._diDashboardHelpers.visMap();

    this._layerDefinitionsCollection.each(this._linkLayerErrors, this);
    this._layerDefinitionsCollection.on('add', this._onLayerDefinitionAdded, this);
    this._layerDefinitionsCollection.on('sync', this._onLayerDefinitionSynced, this);
    this._layerDefinitionsCollection.on('change', this._onLayerDefinitionChanged, this);
    this._layerDefinitionsCollection.on('remove', this._onLayerDefinitionRemoved, this);
    this._layerDefinitionsCollection.on('layerMoved', this._onLayerDefinitionMoved, this);
    this._layerDefinitionsCollection.on('baseLayerChanged', this._onBaseLayerChanged, this);

    this._layerDefinitionsCollection.each(function (layerDefModel) {
      LegendManager.track(layerDefModel);

      linkLayerInfowindow(layerDefModel, this._visMap);
      linkLayerTooltip(layerDefModel, this._visMap);

      if (layerDefModel.has('source')) {
        this._resetStylesIfNoneApplied(layerDefModel);
      }
    }, this);

    // In order to sync layer selector and layer visibility
    this._diDashboardHelpers.getLayers().on('change:visible', function (layer, visible) {
      var layerDefModel = this._layerDefinitionsCollection.findWhere({id: layer.id});
      if (layerDefModel) {
        if (layerDefModel.get('visible') !== visible) {
          layerDefModel.save({visible: visible});
        }
      }
    }, this);

    return this;
  },

  _onLayerDefinitionRemoved: function (m) {
    if (!m.isNew()) {
      var layer = this._diDashboardHelpers.getLayer(m.id);
      layer && layer.remove();
    }
  },

  _onLayerDefinitionMoved: function (m, from, to) {
    this._diDashboardHelpers.moveCartoDBLayer(from, to);
  },

  _createLayer: function (layerDefModel, options) {
    options = options || {};
    var attrs = JSON.parse(JSON.stringify(layerDefModel.attributes)); // deep clone
    attrs = this._adaptAttrsToCDBjs(layerDefModel.get('type'), attrs);

    // create the legends for the new layer
    var legends = this._legendDefinitionsCollection.findByLayerDefModel(layerDefModel);
    if (legends.length > 0) {
      attrs.legends = _.map(legends, function (legend) {
        return legend.toJSON();
      });
    }
    attrs.type = (attrs.layer_name && attrs.layer_name.indexOf('_raster') >= 0) ? 'raster_tileo' : attrs.type;
    var createMethodName = LAYER_TYPE_TO_LAYER_CREATE_METHOD[attrs.type.toLowerCase()];
    if (!createMethodName) throw new Error('no create method name found for type ' + attrs.type);

    if (attrs.source) {
      // Make sure the analysis is created first
      var nodeDefModel = this._analysisDefinitionNodesCollection.get(attrs.source);
      // Dependency with another integration
      this.trigger('onLayerCreation', nodeDefModel);
    }

    var layerPosition = this._layerDefinitionsCollection.indexOf(layerDefModel);
    this._visMap[createMethodName](attrs, _.extend({
      at: layerPosition
    }, options));

    linkLayerInfowindow(layerDefModel, this._visMap);
    linkLayerTooltip(layerDefModel, this._visMap);
    LegendManager.track(layerDefModel);

    this._linkLayerErrors(layerDefModel);
  },

  _linkLayerErrors: function (m) {
    var layer = this._diDashboardHelpers.getLayer(m.id);
    if (layer) {
      if (layer.get('error')) {
        this._setLayerError(m, layer.get('error'));
      }
      layer.on('change:error', function (model, cdbError) {
        this._setLayerError(m, cdbError);
      }, this);
    }
  },

  _setLayerError: function (layerDefinitionModel, cdbError) {
    // Check error is not thrown because of RASTER + the_geom_webmercator
    if (!!(layerDefinitionModel.attributes.table_name.indexOf('raster') > 0) && !!(cdbError.message.indexOf('column "the_geom_webmercator" does not exist') > 0)) {
      return;
    }
    var notification = Notifier.getNotification(layerDefinitionModel.id);
    var mainErrorMessage = layerDefinitionModel.getName() + ': ' + (cdbError && cdbError.message);

    if (!cdbError) {
      layerDefinitionModel.unset('error');
      notification && Notifier.removeNotification(notification);
      return;
    }

    var errorMessage = NotificationErrorMessageHandler.extractError(mainErrorMessage);

    if (notification) {
      notification.update({
        status: errorMessage.type,
        info: errorMessage.message
      });
    } else {
      Notifier.addNotification({
        id: layerDefinitionModel.id,
        status: errorMessage.type,
        closable: true,
        button: false,
        info: errorMessage.message
      });
    }

    if (cdbError.type === 'turbo-carto') {
      var line;
      try {
        line = cdbError.context.source.start.line;
      } catch (error) {}

      layerDefinitionModel.set('error', {
        type: cdbError.type,
        line: line,
        message: cdbError.message
      });
    } else if (errorMessage) {
      layerDefinitionModel.set('error', {
        type: errorMessage.type,
        message: errorMessage.message
      });
    }
  },

  _onLayerDefinitionAdded: function (m, c, opts) {
    // Base and labels layers are synced in a separate method
    if (!layerTypesAndKinds.isTypeDataLayer(m.get('type'))) {
      return;
    }

    // If added but not yet saved, postpone the creation until persisted (see sync listener)
    if (!m.isNew()) {
      if (!this._diDashboardHelpers.getLayer(m.id)) {
        this._createLayer(m);
      } else {
        // we need to sync model positions
        this._tryUpdateLayerPosition(m);
      }
    }
  },

  _tryUpdateLayerPosition: function (m) {
    var builderPosition = this._layerDefinitionsCollection.indexOf(m);
    var cdbLayer = this._diDashboardHelpers.getLayer(m.id);
    var cdbPosition;

    if (cdbLayer) {
      cdbPosition = this._diDashboardHelpers.getLayers().indexOf(cdbLayer);
    }

    var indexChanges = m.isDataLayer() && cdbPosition > 0 && builderPosition > 0 && builderPosition !== cdbPosition;

    if (indexChanges) {
      this._diDashboardHelpers.moveCartoDBLayer(cdbPosition, builderPosition);
    }
  },

  _onLayerDefinitionSynced: function (m) {
    // Base and labels layers are synced in a separate method
    if (!layerTypesAndKinds.isTypeDataLayer(m.get('type'))) {
      return;
    }

    if (!this._diDashboardHelpers.getLayer(m.id)) {
      this._createLayer(m);
    }
  },

  _onLayerDefinitionChanged: function (layerDefinitionModel, changedAttributes) {
    var attrs = layerDefinitionModel.changedAttributes();
    var attrsNames = _.keys(attrs);

    // Base and labels layers are synced in a separate method
    if (!layerTypesAndKinds.isTypeDataLayer(layerDefinitionModel.get('type'))) {
      return;
    }

    // return if only the 'error' attribute has changed (no need to sync anything)
    if (attrsNames.length === 1 && attrsNames[0] === 'error') {
      return;
    }

    var layer = this._diDashboardHelpers.getLayer(layerDefinitionModel.id);
    if (!layerDefinitionModel.isNew()) {
      if (!layer) {
        this._createLayer(layerDefinitionModel);
        return;
      }

      if (attrs.type) {
        layer.remove();
        this._createLayer(layerDefinitionModel);
      } else {
        if (layerDefinitionModel.get('source') && !layer.get('source')) {
          attrs.source = layerDefinitionModel.get('source');
        }
        attrs = this._adaptAttrsToCDBjs(layerDefinitionModel.get('type'), attrs);
        layer.update(attrs);
      }
      // Dependency with widgets-integration
      this.trigger('onLayerChanged', layerDefinitionModel);
    }
  },

  _onBaseLayerChanged: function () {
    var baseLayerDefinition = this._layerDefinitionsCollection.getBaseLayer();
    var newBaseLayerAttrs = baseLayerDefinition.changedAttributes();

    var newBaseLayerType = baseLayerDefinition.get('type');
    var newMapProvider = basemapProvidersAndCategories.getProvider(newBaseLayerType);
    var mapProviderChanged = false;
    if (baseLayerDefinition.hasChanged('type')) {
      var previousBaseLayerType = baseLayerDefinition.previous('type');
      var previousMapProvider = basemapProvidersAndCategories.getProvider(previousBaseLayerType);
      mapProviderChanged = previousMapProvider !== newMapProvider;
    }

    // If the map provider has changed (eg: Leaflet -> Google Maps), we add/update/remove base and
    // labels layers silently so that CartoDB.js doesn't pick up those changes and tries to add/update/remove
    // layers until the new map provider has been set
    var handleLayersSilently = mapProviderChanged;

    // Base layer
    var cdbjsLayer = this._diDashboardHelpers.getLayer(baseLayerDefinition.id);

    // If the type of base layer has changed. eg: Tiled -> Plain
    if (newBaseLayerAttrs.type) {
      cdbjsLayer.remove({ silent: handleLayersSilently });
      this._createLayer(baseLayerDefinition, { silent: handleLayersSilently });
    } else {
      cdbjsLayer.update(this._adaptAttrsToCDBjs(baseLayerDefinition.get('type'), newBaseLayerAttrs), {
        silent: handleLayersSilently
      });
    }

    // Labels layer
    var labelsLayerDefinition = this._layerDefinitionsCollection.getLabelsLayer();
    var cdbjsTopLayer = this._diDashboardHelpers.getLayers().last();
    var cdbjsHasLabelsLayer = cdbjsTopLayer.get('type') === 'Tiled';

    if (labelsLayerDefinition) {
      if (cdbjsHasLabelsLayer) {
        var changedAttrs = labelsLayerDefinition.changedAttributes();
        if (changedAttrs) {
          cdbjsTopLayer.update(this._adaptAttrsToCDBjs(labelsLayerDefinition.get('type'), changedAttrs), {
            silent: handleLayersSilently
          });
        }
      } else {
        this._createLayer(labelsLayerDefinition, { silent: handleLayersSilently });
      }
    } else if (cdbjsHasLabelsLayer) {
      cdbjsTopLayer.remove({ silent: handleLayersSilently });
    }

    // Map provider
    this._visMap.set('provider', newMapProvider);

    if (handleLayersSilently) {
      // Reload map if everything (previously) was done silently
      this._diDashboardHelpers.reloadMap();
    }

    // Render again the edit-feature-overlay, in order to
    // decide if delegate or not events
    this._editFeatureOverlay.render();

    // Dependency with map-integration class
    this.trigger('onBaseLayerChanged');
  },

  _resetStylesIfNoneApplied: function (layerDefModel) {
    var nodeDefModel = layerDefModel.getAnalysisDefinitionNodeModel();
    var analysisCollection = this._diDashboardHelpers.getAnalyses();
    var nodeModel = analysisCollection && analysisCollection.findNodeById(layerDefModel.get('source'));
    var isAnalysisNode = nodeModel && nodeModel.get('type') !== 'source';
    var isDone = nodeModel && nodeModel.isDone();
    var queryGeometryModel = nodeDefModel && nodeDefModel.queryGeometryModel;
    var styleModel = layerDefModel.styleModel;

    if (isAnalysisNode && styleModel.hasNoneStyles() && isDone) {
      var simpleGeom = queryGeometryModel.get('simple_geom');

      var applyDefaultStyles = function () {
        simpleGeom = queryGeometryModel.get('simple_geom');
        styleModel.setDefaultPropertiesByType('simple', simpleGeom);
      };

      if (!simpleGeom) {
        queryGeometryModel.once('change:simple_geom', applyDefaultStyles, this);
        queryGeometryModel.fetch();
      } else {
        applyDefaultStyles();
      }
    }
  },

  _adaptAttrsToCDBjs: function (layerType, attrs) {
    attrs = _.omit(attrs, BLACKLISTED_LAYER_DEFINITION_ATTRS['all'], BLACKLISTED_LAYER_DEFINITION_ATTRS[layerType]);
    _.each(CARTODBJS_TO_CARTODB_ATTRIBUTE_MAPPINGS, function (cdbAttrs, cdbjsAttr) {
      _.each(cdbAttrs, function (cdbAttr) {
        if (attrs[cdbAttr] && !attrs[cdbjsAttr]) {
          attrs[cdbjsAttr] = attrs[cdbAttr];
        }
      });
    });

    return attrs;
  }
};

_.extend(LayersIntegration, Backbone.Events);

module.exports = LayersIntegration;
<|endoftext|>


<commit_before>const { classes: Cc, interfaces: Ci, utils: Cu } = Components;

Cu.import("resource://gre/modules/XPCOMUtils.jsm");

XPCOMUtils.defineLazyModuleGetter(this, "ExtensionUtils",
                                  "resource://gre/modules/ExtensionUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionCommon",
                                  "resource://gre/modules/ExtensionCommon.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionParent",
                                  "resource://gre/modules/ExtensionParent.jsm");

this.reflows = class extends ExtensionAPI {
  getAPI(context) {
    const { windowManager } = context.extension;

    let EventManager = ExtensionCommon.EventManager;

    // Weakly maps XUL windows to their reflow observers.
    let windowMap = new WeakMap();

    return {
      reflows: {
        onUninterruptableReflow: new EventManager(context, "reflow-api", fire => {

          const windowTracker = ExtensionParent.apiManager.global.windowTracker;
          let windows = Array.from(windowManager.getAll(), win => win.window);

          let observeWindow = (win) => {
            let observer = {
              reflow(start, end) {
                // Grab the stack, but slice off the top frame inside this observer.
                let stack = new Error().stack.split("\n").slice(1).join("\n");
                // If the stack string is empty, and a debugger is attached, try to
                // hit a breakpoint.
                if (!stack) {
                  let debug = Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2);
                  if (debug.isDebuggerAttached) {
                    debug.break("api.js", -1);
                  }
                }

                let id = windowTracker.getId(win);
                fire.async(id, start, end, stack);
              },
              reflowInterruptible(start, end) {},
              QueryInterface: ChromeUtils.generateQI([Ci.nsIReflowObserver,
                                                      Ci.nsISupportsWeakReference])
            };

            let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
                              .getInterface(Ci.nsIWebNavigation)
                              .QueryInterface(Ci.nsIDocShell);
            docShell.addWeakReflowObserver(observer);

            windowMap.set(win, observer);
          };

          for (let win of windows) {
            observeWindow(win);
          }

          let windowOpenListener = (win) => {
            observeWindow(win);
          }

          windowTracker.addListener("domwindowopened", windowOpenListener);
          windows = [];

          return () => {
            let windows = Array.from(windowManager.getAll(), win => win.window);
            for (let win of windows) {
              let observer = windowMap.get(win);
              if (observer) {
                let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
                                  .getInterface(Ci.nsIWebNavigation)
                                  .QueryInterface(Ci.nsIDocShell);
                docShell.removeWeakReflowObserver(observer);
              }

              windowMap.delete(win);
            }

            windowTracker.removeListener("domwindowopened", windowOpenListener);
          }

        }).api()
      }
    };
  }
}

<commit_msg>Make work after bug 1451212.<commit_after>const { classes: Cc, interfaces: Ci, utils: Cu } = Components;

Cu.import("resource://gre/modules/XPCOMUtils.jsm");

XPCOMUtils.defineLazyModuleGetter(this, "ExtensionUtils",
                                  "resource://gre/modules/ExtensionUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionCommon",
                                  "resource://gre/modules/ExtensionCommon.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionParent",
                                  "resource://gre/modules/ExtensionParent.jsm");

this.reflows = class extends ExtensionAPI {
  getAPI(context) {
    const { windowManager } = context.extension;

    let EventManager = ExtensionCommon.EventManager;

    // Weakly maps XUL windows to their reflow observers.
    let windowMap = new WeakMap();

    return {
      reflows: {
        onUninterruptableReflow: new EventManager({
          context,
          name: "reflow-api",
          register: fire => {
            const windowTracker = ExtensionParent.apiManager.global.windowTracker;
            let windows = Array.from(windowManager.getAll(), win => win.window);

            let observeWindow = (win) => {
              let observer = {
                reflow(start, end) {
                  // Grab the stack, but slice off the top frame inside this observer.
                  let stack = new Error().stack.split("\n").slice(1).join("\n");
                  // If the stack string is empty, and a debugger is attached, try to
                  // hit a breakpoint.
                  if (!stack) {
                    let debug = Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2);
                    if (debug.isDebuggerAttached) {
                      debug.break("api.js", -1);
                    }
                  }

                  let id = windowTracker.getId(win);
                  fire.async(id, start, end, stack);
                },
                reflowInterruptible(start, end) {},
                QueryInterface: ChromeUtils.generateQI([Ci.nsIReflowObserver,
                                                        Ci.nsISupportsWeakReference])
              };

              win.docShell.addWeakReflowObserver(observer);

              windowMap.set(win, observer);
            };

            for (let win of windows) {
              observeWindow(win);
            }

            let windowOpenListener = (win) => {
              observeWindow(win);
            }

            windowTracker.addListener("domwindowopened", windowOpenListener);
            windows = [];

            return () => {
              let windows = Array.from(windowManager.getAll(), win => win.window);
              for (let win of windows) {
                let observer = windowMap.get(win);
                if (observer) {
                  win.docShell.removeWeakReflowObserver(observer);
                }

                windowMap.delete(win);
              }

              windowTracker.removeListener("domwindowopened", windowOpenListener);
            }
          }
        }).api()
      }
    };
  }
}

<|endoftext|>


<commit_before>let express = require('express')
let bodyParser = require('body-parser')
let jsonfile = require('jsonfile')
let path = require('path')
let fs = require('fs')
let app = express()

let pathJsonFile = path.join(__dirname, '/json/translate/')
let pathApi = '/api'
jsonfile.spaces = 2

app.use(function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*')
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
  next()
})
app.use(bodyParser.json())

function isDefined (value) { return value !== undefined }

function createFolderIsNotExist (pathFolder) {
  if (!fs.existsSync(path.join(__dirname, pathFolder))) {
    fs.mkdir(path.join(__dirname, pathFolder), function (err) {
      if (!err || (err && err.code === 'EEXIST')) {
        console.log('Successful creation for the', pathFolder, 'folder on path', __dirname)
      } else {
        console.log('Error on create folder', pathFolder, 'on path', __dirname, err)
      }
    })
  }
}

function searchGroup (obj, groups, value, action, i) {
  for (let key in obj) {
    if (key === groups[i]) {
      if (key === groups[i] && i === groups.length - 1) {
        if (action === 'add' || action === 'upd') {
          if (typeof value === 'object') {
            obj[key][value.key] = value.trad
          } else {
            obj[key][value] = {}
          }
          return obj
        } else if (action === 'del') {
          if (typeof value === 'object') {
            delete obj[key][value.key]
          } else {
            delete obj[key][value]
          }
          return obj
        }
      }
      i++
      searchGroup(obj[key], groups, value, action, i)
    }
  }
}

createFolderIsNotExist('/json/')
createFolderIsNotExist('/json/translate/')

app.get('/', function (req, res) {
  res.send('Hello Node !')
})

app.get(pathApi + '/list-lang', function (req, res) {
  fs.readdir(pathJsonFile, function (err, files) {
    if (err) { throw err }

    let langs = { listLangs: [] }
    files.forEach(function (file) {
      langs.listLangs.push(file.substring(0, 2))
    })

    res.send(langs)
  })
})

app.get(pathApi + '/create/:lang', function (req, res) {
  let file = pathJsonFile + req.params.lang + '.json'
  let obj = {}

  jsonfile.writeFile(file, obj, function (err) {
    if (err) { return console.log('Error on create json file', err) }
    res.sendStatus(200)
  })
})

app.get(pathApi + '/delete/:lang', function (req, res) {
  fs.stat(pathJsonFile + req.params.lang + '.json', function (err, stats) {
    if (err) { return console.error(err) }

    fs.unlink(pathJsonFile + req.params.lang + '.json', function (err) {
      if (err) { return console.log(err) }
      console.log('file "' + req.params.lang + '.json" deleted successfully')
      res.sendStatus(200)
    })
  })
})

app.get(pathApi + '/open/:lang', function (req, res) {
  res.sendFile(pathJsonFile + req.params.lang + '.json')
})

app.get(pathApi + '/download/:lang', function (req, res) {
  res.sendFile(pathJsonFile + req.params.lang + '.json')
})

app.post(pathApi + '/:lang/group/add', function (req, res) {
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      obj[req.body.groupName] = {}
    } else {
      let i = 0
      searchGroup(obj, groups, req.body.groupName, 'add', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on add group name on json file', err) }
      res.sendStatus(200)
    })
  })
})

app.post(pathApi + '/:lang/group/maj', function (req, res) {
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      var copyGroup = obj[req.body.originalGroupName]
      delete obj[req.body.originalGroupName]
      obj[req.body.groupName] = copyGroup
    } else {
      let i = 0
      searchGroup(obj, groups, req.body.originalGroupName, 'upd', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on update group name on json file', err) }
      res.sendStatus(200)
    })
  })
})

app.post(pathApi + '/:lang/group/del', function (req, res) {
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      delete obj[req.body.groupName]
    } else {
      let i = 0
      searchGroup(obj, groups, req.body.groupName, 'del', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on delete group name on json file', err) }
      res.sendStatus(200)
    })
  })
})

app.post(pathApi + '/:lang/trad/add', function (req, res) {
  let trad = req.body.trad
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      obj[trad.key] = trad.trad
    } else {
      let i = 0
      searchGroup(obj, groups, trad, 'add', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on add trad on json file', err) }
      res.sendStatus(200)
    })
  })
})

app.post(pathApi + '/:lang/trad/maj', function (req, res) {
  let trad = req.body.trad
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      obj[trad.key] = trad.trad
    } else {
      let i = 0
      searchGroup(obj, groups, trad, 'upd', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on update trad on json file', err) }
      res.sendStatus(200)
    })
  })
})

app.post(pathApi + '/:lang/trad/del', function (req, res) {
  let trad = req.body.trad
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      delete obj[trad.key]
    } else {
      let i = 0
      searchGroup(obj, groups, trad, 'del', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on delete trad on json file', err) }
      res.sendStatus(200)
    })
  })
})

let server = app.listen(7777, 'localhost', function () {
  console.log('API listen on ' + server.address().address + ':' + server.address().port + ' !')
})
<commit_msg>improve maj name of sub group<commit_after>let express = require('express')
let bodyParser = require('body-parser')
let jsonfile = require('jsonfile')
let path = require('path')
let fs = require('fs')
let app = express()

let pathJsonFile = path.join(__dirname, '/json/translate/')
let pathApi = '/api'
jsonfile.spaces = 2

app.use(function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*')
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
  next()
})
app.use(bodyParser.json())

function isDefined (value) { return value !== undefined }

function createFolderIsNotExist (pathFolder) {
  if (!fs.existsSync(path.join(__dirname, pathFolder))) {
    fs.mkdir(path.join(__dirname, pathFolder), function (err) {
      if (!err || (err && err.code === 'EEXIST')) {
        console.log('Successful creation for the', pathFolder, 'folder on path', __dirname)
      } else {
        console.log('Error on create folder', pathFolder, 'on path', __dirname, err)
      }
    })
  }
}

function searchGroup (obj, groups, value, action, i, newGroupName) {
  for (let key in obj) {
    if (key === groups[i]) {
      if (key === groups[i] && i === groups.length - 1) {
        if (action === 'add' || action === 'upd') {
          if (typeof value === 'object') {
            obj[key][value.key] = value.trad
          } else {
            if (action === 'add') {
              obj[key][value] = {}
            }
            if (action === 'upd') {
              var copyGroup = obj[key][value]
              delete obj[key][value]
              obj[key][newGroupName] = copyGroup
            }
          }
          return obj
        } else if (action === 'del') {
          if (typeof value === 'object') {
            delete obj[key][value.key]
          } else {
            delete obj[key][value]
          }
          return obj
        }
      }
      i++
      searchGroup(obj[key], groups, value, action, i, newGroupName)
    }
  }
}

createFolderIsNotExist('/json/')
createFolderIsNotExist('/json/translate/')

app.get('/', function (req, res) {
  res.send('Hello Node !')
})

app.get(pathApi + '/list-lang', function (req, res) {
  fs.readdir(pathJsonFile, function (err, files) {
    if (err) { throw err }

    let langs = { listLangs: [] }
    files.forEach(function (file) {
      langs.listLangs.push(file.substring(0, 2))
    })

    res.send(langs)
  })
})

app.get(pathApi + '/create/:lang', function (req, res) {
  let file = pathJsonFile + req.params.lang + '.json'
  let obj = {}

  jsonfile.writeFile(file, obj, function (err) {
    if (err) { return console.log('Error on create json file', err) }
    res.sendStatus(200)
  })
})

app.get(pathApi + '/delete/:lang', function (req, res) {
  fs.stat(pathJsonFile + req.params.lang + '.json', function (err, stats) {
    if (err) { return console.error(err) }

    fs.unlink(pathJsonFile + req.params.lang + '.json', function (err) {
      if (err) { return console.log(err) }
      console.log('file "' + req.params.lang + '.json" deleted successfully')
      res.sendStatus(200)
    })
  })
})

app.get(pathApi + '/open/:lang', function (req, res) {
  res.sendFile(pathJsonFile + req.params.lang + '.json')
})

app.get(pathApi + '/download/:lang', function (req, res) {
  res.sendFile(pathJsonFile + req.params.lang + '.json')
})

app.post(pathApi + '/:lang/group/add', function (req, res) {
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      obj[req.body.groupName] = {}
    } else {
      let i = 0
      searchGroup(obj, groups, req.body.groupName, 'add', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on add group name on json file', err) }
      res.sendStatus(200)
    })
  })
})

app.post(pathApi + '/:lang/group/maj', function (req, res) {
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      var copyGroup = obj[req.body.originalGroupName]
      delete obj[req.body.originalGroupName]
      obj[req.body.groupName] = copyGroup
    } else {
      let i = 0
      searchGroup(obj, groups, req.body.originalGroupName, 'upd', i, req.body.groupName)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on update group name on json file', err) }
      res.sendStatus(200)
    })
  })
})

app.post(pathApi + '/:lang/group/del', function (req, res) {
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      delete obj[req.body.groupName]
    } else {
      let i = 0
      searchGroup(obj, groups, req.body.groupName, 'del', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on delete group name on json file', err) }
      res.sendStatus(200)
    })
  })
})

app.post(pathApi + '/:lang/trad/add', function (req, res) {
  let trad = req.body.trad
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      obj[trad.key] = trad.trad
    } else {
      let i = 0
      searchGroup(obj, groups, trad, 'add', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on add trad on json file', err) }
      res.sendStatus(200)
    })
  })
})

app.post(pathApi + '/:lang/trad/maj', function (req, res) {
  let trad = req.body.trad
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      obj[trad.key] = trad.trad
    } else {
      let i = 0
      searchGroup(obj, groups, trad, 'upd', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on update trad on json file', err) }
      res.sendStatus(200)
    })
  })
})

app.post(pathApi + '/:lang/trad/del', function (req, res) {
  let trad = req.body.trad
  let groups = isDefined(req.body.groups) ? req.body.groups.split('/') : undefined
  let file = pathJsonFile + req.params.lang + '.json'
  jsonfile.readFile(file, function (err, obj) {
    if (err) { console.log('Error on read json file', err) }
    if (!isDefined(groups)) {
      delete obj[trad.key]
    } else {
      let i = 0
      searchGroup(obj, groups, trad, 'del', i)
    }
    jsonfile.writeFile(file, obj, function (err) {
      if (err) { return console.log('Error on delete trad on json file', err) }
      res.sendStatus(200)
    })
  })
})

let server = app.listen(7777, 'localhost', function () {
  console.log('API listen on ' + server.address().address + ':' + server.address().port + ' !')
})
<|endoftext|>


<commit_before>;(function(){

  angular
    .module('app.controllers.HomeController', [
      'app.services.routes',
      'app.services.user',
      'checklist-model'
    ])
    .controller('HomeController', HomeController);

  HomeController.$inject = [
    '$http',
    'routes',
    'user'
  ];

  /**
  * the home controller is responsible for displaying the info on the main page of the app
  * It stores and displays data on what routes the user has available to them
  * This page serves as a jumping off point to editing individual routes and makes
  * adding and removing new routes easy
  */
  //runs activate on startup

  function HomeController($http, routes, user, checklist) {
    var vm = this;
    vm.formInfo = {};
    vm.formInfo.methods = [];
    vm.formInfo.body = {};
    vm.routes = routes.routes;
    vm.user = {};
    vm.verbs = ['GET', 'POST', 'PUT', 'DELETE'];

    vm.addRoute = addRoute;
    vm.toggleRoute = toggleRoute;

    activate();

    /////////////////////////

    /**
    * Activate gets called on module load and calls fetch which fetches user data
    * from the database and displays it for the user
    */
    function activate() {
      user.registerCb(function(){
        vm.user = user.getUser();
        routes.fetch(vm.user.username).then(function() {
        });
      });

    }

    /**
    * Process to capture and add route information from the user then store them in
    * the database
    */
    function addRoute() {
      routes.addRoute(vm.formInfo, vm.user.username).then(function() {

        //resets the the text box back to empty
        vm.formInfo.route = '';
      });
    }

    /**
     * handles logic for when user checks and unchecks a method for a route.
     * When unchecking, deletes that method from the route. When checking,
     * adds a new set of body data for user to input
     */
    function toggleRoute(method) {
      // delete method from body if present
      if (typeof vm.formInfo.body[method] !== 'undefined') {
        delete vm.formInfo.body[method];

      // otherwise add it to the form
      } else {
        vm.formInfo.body[method] = '';
      }

      // update keys
      vm.formInfo.methods = Object.keys(vm.formInfo.body);
    }

    //TODO Add functionality here
    function editRoute() {}

    //TODO Add functionality here
    function deleteRoute() {
      routes.deleteRoute();
    }

  }

})();
<commit_msg>addressed issues from github<commit_after>;(function(){

  angular
    .module('app.controllers.HomeController', [
      'app.services.routes',
      'app.services.user',
      'checklist-model'
    ])
    .controller('HomeController', HomeController);

  HomeController.$inject = [
    '$http',
    'routes',
    'user'
  ];

  /**
  * the home controller is responsible for displaying the info on the main page of the app
  * It stores and displays data on what routes the user has available to them
  * This page serves as a jumping off point to editing individual routes and makes
  * adding and removing new routes easy
  */
  //runs activate on startup

  function HomeController($http, routes, user, checklist) {
    var vm = this;
    vm.formInfo = {
      methods: [],
      body: {}
    };
    vm.routes = routes.routes;
    vm.verbs = ['GET', 'POST', 'PUT', 'DELETE'];

    vm.addRoute = addRoute;
    vm.toggleRoute = toggleRoute;

    activate();

    /////////////////////////

    /**
    * Activate gets called on module load and calls fetch which fetches user data
    * from the database and displays it for the user
    */
    function activate() {
      user.registerCb(function(){
        routes.fetch(user.getUser().username)
          .then(function() {});
      });

    }

    /**
    * Process to capture and add route information from the user then store them in
    * the database
    */
    function addRoute() {
      routes.addRoute(vm.formInfo, user.getUser().username)
        .then(function() {

          //resets the the text box back to empty
          vm.formInfo.route = '';
        });
    }

    /**
     * handles logic for when user checks and unchecks a method for a route.
     * When unchecking, deletes that method from the route. When checking,
     * adds a new set of body data for user to input
     */
    function toggleRoute(method) {
      // delete method from body if present
      if (typeof vm.formInfo.body[method] !== 'undefined') {
        delete vm.formInfo.body[method];

      // otherwise add it to the form
      } else {
        vm.formInfo.body[method] = '';
      }

      // update keys
      vm.formInfo.methods = Object.keys(vm.formInfo.body);
    }

    //TODO Add functionality here
    function editRoute() {}

    //TODO Add functionality here
    function deleteRoute() {
      routes.deleteRoute();
    }

  }

})();
<|endoftext|>


<commit_before>import hammerhead from '../../deps/hammerhead';
import testCafeCore from '../../deps/testcafe-core';

var browserUtils = hammerhead.utils.browser;

var domUtils        = testCafeCore.domUtils;
var positionUtils   = testCafeCore.positionUtils;
var styleUtils      = testCafeCore.styleUtils;
var contentEditable = testCafeCore.contentEditable;
var arrayUtils      = testCafeCore.arrayUtils;

const MODIFIERS_LIST = ['direction', 'font-family', 'font-size', 'font-size-adjust', 'font-variant', 'font-weight', 'font-style', 'letter-spacing', 'line-height', 'text-align', 'text-indent', 'text-transform', 'word-wrap', 'word-spacing', 'padding-top', 'padding-left', 'padding-right', 'padding-bottom', 'margin-top', 'margin-left', 'margin-right', 'margin-bottom', 'border-top-width', 'border-left-width', 'border-right-width', 'border-bottom-width'];

function ensureRectangleInsideElement (element, rect) {
    var elementBorders = styleUtils.getBordersWidth(element);
    var elementOffset  = positionUtils.getOffsetPosition(element);

    // NOTE: strange behavior in Chrome - for some elements (e.g., for the 'font' element)
    // scrollHeight is 0, so we use getBoundingClientRect
    var elementHeight = element.scrollHeight || element.getBoundingClientRect().height;
    var left          = Math.ceil(rect.left);
    var top           = Math.ceil(rect.top);
    var bottom        = Math.floor(rect.bottom);

    if (!domUtils.isTextAreaElement(element)) {
        var clientOffset = positionUtils.offsetToClientCoords({
            x: elementOffset.left,
            y: elementOffset.top
        });

        var minLeft     = clientOffset.x + elementBorders.left + 1;
        var minTop      = clientOffset.y + elementBorders.top + 1;
        var bottomBound = clientOffset.y + elementBorders.top + elementBorders.bottom + elementHeight;
        var maxBottom   = rect.top + elementHeight - 1;

        left   = Math.ceil(left <= clientOffset.x ? minLeft : rect.left);
        top    = Math.ceil(top <= clientOffset.y ? minTop : rect.top);
        bottom = Math.floor(bottom >= bottomBound ? maxBottom : rect.bottom);
    }

    return {
        left:   left,
        top:    top,
        bottom: bottom
    };
}

function getAbsoluteRect (rect) {
    var documentScroll = styleUtils.getElementScroll(document);

    return {
        left:   rect.left + documentScroll.left,
        top:    rect.top + documentScroll.top,
        bottom: rect.bottom + documentScroll.top
    };
}

function getSelectionRectangleInContentEditableElement (element, position) {
    var range             = domUtils.findDocument(element).createRange();
    var selectionPosition = contentEditable.calculateNodeAndOffsetByPosition(element, position);

    range.setStart(selectionPosition.node, Math.min(selectionPosition.offset, selectionPosition.node.length));
    range.setEnd(selectionPosition.node, Math.min(selectionPosition.offset, selectionPosition.node.length));

    return range.getClientRects()[0];
}

function getTextSelectionRectangle (element, position) {
    var range = element.createTextRange();

    range.collapse(true);
    range.moveStart('character', position);
    range.moveEnd('character', position);
    range.collapse(true);

    return range.getBoundingClientRect();
}

function getSelectionRectangle (element, position) {
    var fakeDiv = createFakeDiv(element);
    var rect    = null;

    try {
        var range = document.createRange(); //B254723

        range.setStart(fakeDiv.firstChild, Math.min(position, element.value.length));
        range.setEnd(fakeDiv.firstChild, Math.min(position, element.value.length));

        if (domUtils.isTextAreaElement(element)) {
            rect = range.getBoundingClientRect();

            if (rect.width === 0 && rect.height === 0)
                rect = range.getClientRects()[0];
        }
        else
            rect = range.getClientRects()[0];
    }
    catch (err) {
        rect = null;
    }

    domUtils.remove(fakeDiv);

    return rect;
}

function createFakeDiv (element) {
    var body          = document.body;
    var elementOffset = positionUtils.getOffsetPosition(element);
    var elementMargin = styleUtils.getElementMargin(element);
    var elementTop    = elementOffset.top - elementMargin.top;
    var elementLeft   = elementOffset.left - elementMargin.left;

    var fakeDiv          = document.createElement('div');
    var fakeDivCssStyles = 'white-space:pre-wrap;border-style:solid;';

    if (styleUtils.get(body, 'position') === 'absolute') {
        var bodyMargin = styleUtils.getElementMargin(body);
        var bodyLeft   = styleUtils.get(body, 'left');
        var bodyTop    = styleUtils.get(body, 'top');

        elementLeft -= bodyMargin.left + (parseInt(bodyLeft.replace('px', ''), 10) || 0);
        elementTop -= bodyMargin.top + (parseInt(bodyTop.replace('px', ''), 10) || 0);
    }

    arrayUtils.forEach(MODIFIERS_LIST, modifier => {
        fakeDivCssStyles += `${modifier}:${styleUtils.get(element, modifier)};`;
    });

    styleUtils.set(fakeDiv, {
        cssText:  fakeDivCssStyles,
        position: 'absolute',
        left:     elementLeft + 'px',
        top:      elementTop + 'px',
        width:    element.scrollWidth + 'px',
        height:   element.scrollHeight + 'px'
    });

    fakeDiv.textContent = !element.value.length ? ' ' : element.value;

    body.appendChild(fakeDiv);

    return fakeDiv;
}

function getPositionCoordinates (element, position) {
    var rect = null;

    if (domUtils.isContentEditableElement(element))
        rect = getSelectionRectangleInContentEditableElement(element, position);
    else if (typeof element.createTextRange === 'function')
        rect = getTextSelectionRectangle(element, position);
    else
        rect = getSelectionRectangle(element, position);

    if (!rect)
        return null;

    rect = ensureRectangleInsideElement(element, rect);
    rect = getAbsoluteRect(rect);

    return {
        x: rect.left,
        y: Math.floor(rect.top + (rect.bottom - rect.top) / 2)
    };
}

export function getSelectionCoordinatesByPosition (element, position) {
    var isTextEditable    = domUtils.isTextEditableElement(element);
    var isContentEditable = domUtils.isContentEditableElement(element);
    var hasText           = isTextEditable && element.value.length > 0 ||
                            isContentEditable && contentEditable.getContentEditableValue(element).length;

    if (!hasText)
        return positionUtils.findCenter(element);

    return getPositionCoordinates(element, position);
}

export function getSelectionCoordinatesByNodeAndOffset (element, node, offset) {
    var range = domUtils.findDocument(element).createRange();

    range.setStart(node, Math.min(offset, node.length));
    range.setEnd(node, Math.min(offset, node.length));

    var rect = range.getClientRects()[0];

    if (!rect)
        return null;

    rect = ensureRectangleInsideElement(element, rect);
    rect = getAbsoluteRect(rect);

    return {
        x: rect.left,
        y: Math.floor(rect.top + (rect.bottom - rect.top) / 2)
    };
}

export function getLastVisibleSelectionPosition (element, startPos, endPos) {
    var backward     = startPos > endPos;
    var inc          = backward ? 1 : -1;
    var currentPos   = endPos;
    var currentPoint = null;

    while (currentPos !== startPos) {
        currentPos += inc;
        currentPoint = getPositionCoordinates(element, currentPos);

        if (currentPoint)
            break;
    }

    if (!currentPoint) {
        currentPoint = getPositionCoordinates(element, startPos) ||
                       positionUtils.findCenter(element);
    }

    return currentPoint;
}

export function scrollEditableElementByPoint (element, point) {
    if (!domUtils.isEditableElement(element))
        return;

    var isTextarea     = domUtils.isTextAreaElement(element);
    var isInputElement = domUtils.isInputElement(element);

    // NOTE: we don't need to scroll input elements in Mozilla and
    // IE > 10 because it happens automatically on selection setting
    if (isInputElement && (browserUtils.isFirefox || browserUtils.isIE && browserUtils.version > 10))
        return;

    var elementOffset  = positionUtils.getOffsetPosition(element);
    var elementBorders = styleUtils.getBordersWidth(element);
    var elementScroll  = styleUtils.getElementScroll(element);

    var offsetX     = point.x - elementOffset.left - elementBorders.left;
    var offsetY     = point.y - elementOffset.top - elementBorders.top;
    var scrollValue = null;

    if (isTextarea) {
        if (offsetY < elementScroll.top)
            scrollValue = offsetY;

        if (offsetY > element.clientHeight + elementScroll.top)
            scrollValue = offsetY - element.clientHeight;

        if (scrollValue !== null)
            styleUtils.setScrollTop(element, Math.round(scrollValue));

        return;
    }

    if (offsetX < elementScroll.left)
        scrollValue = offsetX;

    if (offsetX > element.clientWidth + elementScroll.left)
        scrollValue = offsetX - element.clientWidth;

    if (scrollValue !== null)
        styleUtils.setScrollLeft(element, Math.round(scrollValue));
}

export function excludeElementScroll (element, point) {
    var isTextEditable = domUtils.isTextEditableElement(element);
    var isInputElement = domUtils.isInputElement(element);

    if (!(isTextEditable || domUtils.isContentEditableElement(element)))
        return point;

    var elementOffset  = positionUtils.getOffsetPosition(element);
    var elementBorders = styleUtils.getBordersWidth(element);
    var elementScroll  = styleUtils.getElementScroll(element);
    var maxLeft        = elementOffset.left + elementBorders.left + element.clientWidth;

    // NOTE: we can't know input elements' scroll value in Mozilla and
    // IE > 10 (https://bugzilla.mozilla.org/show_bug.cgi?id=293186)
    if (isInputElement && isTextEditable &&
        (browserUtils.isFirefox || browserUtils.isIE && browserUtils.version > 10)) {
        return {
            x: Math.min(point.x, maxLeft),
            y: point.y
        };
    }

    return {
        x: point.x - elementScroll.left,
        y: point.y - elementScroll.top
    };
}
<commit_msg>fix functional test in MSEdge (#797)<commit_after>import hammerhead from '../../deps/hammerhead';
import testCafeCore from '../../deps/testcafe-core';

var browserUtils = hammerhead.utils.browser;

var domUtils        = testCafeCore.domUtils;
var positionUtils   = testCafeCore.positionUtils;
var styleUtils      = testCafeCore.styleUtils;
var contentEditable = testCafeCore.contentEditable;
var arrayUtils      = testCafeCore.arrayUtils;

const MODIFIERS_LIST = ['direction', 'font-family', 'font-size', 'font-size-adjust', 'font-variant', 'font-weight', 'font-style', 'letter-spacing', 'line-height', 'text-align', 'text-indent', 'text-transform', 'word-wrap', 'word-spacing', 'padding-top', 'padding-left', 'padding-right', 'padding-bottom', 'margin-top', 'margin-left', 'margin-right', 'margin-bottom', 'border-top-width', 'border-left-width', 'border-right-width', 'border-bottom-width'];

function ensureRectangleInsideElement (element, rect) {
    var elementBorders = styleUtils.getBordersWidth(element);
    var elementOffset  = positionUtils.getOffsetPosition(element);

    // NOTE: strange behavior in Chrome - for some elements (e.g., for the 'font' element)
    // scrollHeight is 0, so we use getBoundingClientRect
    var elementHeight = element.scrollHeight || element.getBoundingClientRect().height;
    var left          = Math.ceil(rect.left);
    var top           = Math.ceil(rect.top);
    var bottom        = Math.floor(rect.bottom);

    if (!domUtils.isTextAreaElement(element)) {
        var clientOffset = positionUtils.offsetToClientCoords({
            x: elementOffset.left,
            y: elementOffset.top
        });

        var minLeft     = clientOffset.x + elementBorders.left + 1;
        var minTop      = clientOffset.y + elementBorders.top + 1;
        var bottomBound = clientOffset.y + elementBorders.top + elementBorders.bottom + elementHeight;
        var maxBottom   = clientOffset.y + elementBorders.top + elementHeight - 1;

        left   = Math.ceil(left <= clientOffset.x ? minLeft : rect.left);
        top    = Math.ceil(top <= clientOffset.y ? minTop : rect.top);
        bottom = Math.floor(bottom >= bottomBound ? maxBottom : rect.bottom);
    }

    return {
        left:   left,
        top:    top,
        bottom: bottom
    };
}

function getAbsoluteRect (rect) {
    var documentScroll = styleUtils.getElementScroll(document);

    return {
        left:   rect.left + documentScroll.left,
        top:    rect.top + documentScroll.top,
        bottom: rect.bottom + documentScroll.top
    };
}

function getSelectionRectangleInContentEditableElement (element, position) {
    var range             = domUtils.findDocument(element).createRange();
    var selectionPosition = contentEditable.calculateNodeAndOffsetByPosition(element, position);

    range.setStart(selectionPosition.node, Math.min(selectionPosition.offset, selectionPosition.node.length));
    range.setEnd(selectionPosition.node, Math.min(selectionPosition.offset, selectionPosition.node.length));

    return range.getClientRects()[0];
}

function getTextSelectionRectangle (element, position) {
    var range = element.createTextRange();

    range.collapse(true);
    range.moveStart('character', position);
    range.moveEnd('character', position);
    range.collapse(true);

    return range.getBoundingClientRect();
}

function getSelectionRectangle (element, position) {
    var fakeDiv = createFakeDiv(element);
    var rect    = null;

    try {
        var range = document.createRange(); //B254723

        range.setStart(fakeDiv.firstChild, Math.min(position, element.value.length));
        range.setEnd(fakeDiv.firstChild, Math.min(position, element.value.length));

        if (domUtils.isTextAreaElement(element)) {
            rect = range.getBoundingClientRect();

            if (rect.width === 0 && rect.height === 0)
                rect = range.getClientRects()[0];
        }
        else
            rect = range.getClientRects()[0];
    }
    catch (err) {
        rect = null;
    }

    domUtils.remove(fakeDiv);

    return rect;
}

function createFakeDiv (element) {
    var body          = document.body;
    var elementOffset = positionUtils.getOffsetPosition(element);
    var elementMargin = styleUtils.getElementMargin(element);
    var elementTop    = elementOffset.top - elementMargin.top;
    var elementLeft   = elementOffset.left - elementMargin.left;

    var fakeDiv          = document.createElement('div');
    var fakeDivCssStyles = 'white-space:pre-wrap;border-style:solid;';

    if (styleUtils.get(body, 'position') === 'absolute') {
        var bodyMargin = styleUtils.getElementMargin(body);
        var bodyLeft   = styleUtils.get(body, 'left');
        var bodyTop    = styleUtils.get(body, 'top');

        elementLeft -= bodyMargin.left + (parseInt(bodyLeft.replace('px', ''), 10) || 0);
        elementTop -= bodyMargin.top + (parseInt(bodyTop.replace('px', ''), 10) || 0);
    }

    arrayUtils.forEach(MODIFIERS_LIST, modifier => {
        fakeDivCssStyles += `${modifier}:${styleUtils.get(element, modifier)};`;
    });

    styleUtils.set(fakeDiv, {
        cssText:  fakeDivCssStyles,
        position: 'absolute',
        left:     elementLeft + 'px',
        top:      elementTop + 'px',
        width:    element.scrollWidth + 'px',
        height:   element.scrollHeight + 'px'
    });

    fakeDiv.textContent = !element.value.length ? ' ' : element.value;

    body.appendChild(fakeDiv);

    return fakeDiv;
}

function getPositionCoordinates (element, position) {
    var rect = null;

    if (domUtils.isContentEditableElement(element))
        rect = getSelectionRectangleInContentEditableElement(element, position);
    else if (typeof element.createTextRange === 'function')
        rect = getTextSelectionRectangle(element, position);
    else
        rect = getSelectionRectangle(element, position);

    if (!rect)
        return null;

    rect = ensureRectangleInsideElement(element, rect);
    rect = getAbsoluteRect(rect);

    return {
        x: rect.left,
        y: Math.floor(rect.top + (rect.bottom - rect.top) / 2)
    };
}

export function getSelectionCoordinatesByPosition (element, position) {
    var isTextEditable    = domUtils.isTextEditableElement(element);
    var isContentEditable = domUtils.isContentEditableElement(element);
    var hasText           = isTextEditable && element.value.length > 0 ||
                            isContentEditable && contentEditable.getContentEditableValue(element).length;

    if (!hasText)
        return positionUtils.findCenter(element);

    return getPositionCoordinates(element, position);
}

export function getSelectionCoordinatesByNodeAndOffset (element, node, offset) {
    var range = domUtils.findDocument(element).createRange();

    range.setStart(node, Math.min(offset, node.length));
    range.setEnd(node, Math.min(offset, node.length));

    var rect = range.getClientRects()[0];

    if (!rect)
        return null;

    rect = ensureRectangleInsideElement(element, rect);
    rect = getAbsoluteRect(rect);

    return {
        x: rect.left,
        y: Math.floor(rect.top + (rect.bottom - rect.top) / 2)
    };
}

export function getLastVisibleSelectionPosition (element, startPos, endPos) {
    var backward     = startPos > endPos;
    var inc          = backward ? 1 : -1;
    var currentPos   = endPos;
    var currentPoint = null;

    while (currentPos !== startPos) {
        currentPos += inc;
        currentPoint = getPositionCoordinates(element, currentPos);

        if (currentPoint)
            break;
    }

    if (!currentPoint) {
        currentPoint = getPositionCoordinates(element, startPos) ||
                       positionUtils.findCenter(element);
    }

    return currentPoint;
}

export function scrollEditableElementByPoint (element, point) {
    if (!domUtils.isEditableElement(element))
        return;

    var isTextarea     = domUtils.isTextAreaElement(element);
    var isInputElement = domUtils.isInputElement(element);

    // NOTE: we don't need to scroll input elements in Mozilla and
    // IE > 10 because it happens automatically on selection setting
    if (isInputElement && (browserUtils.isFirefox || browserUtils.isIE && browserUtils.version > 10))
        return;

    var elementOffset  = positionUtils.getOffsetPosition(element);
    var elementBorders = styleUtils.getBordersWidth(element);
    var elementScroll  = styleUtils.getElementScroll(element);

    var offsetX     = point.x - elementOffset.left - elementBorders.left;
    var offsetY     = point.y - elementOffset.top - elementBorders.top;
    var scrollValue = null;

    if (isTextarea) {
        if (offsetY < elementScroll.top)
            scrollValue = offsetY;

        if (offsetY > element.clientHeight + elementScroll.top)
            scrollValue = offsetY - element.clientHeight;

        if (scrollValue !== null)
            styleUtils.setScrollTop(element, Math.round(scrollValue));

        return;
    }

    if (offsetX < elementScroll.left)
        scrollValue = offsetX;

    if (offsetX > element.clientWidth + elementScroll.left)
        scrollValue = offsetX - element.clientWidth;

    if (scrollValue !== null)
        styleUtils.setScrollLeft(element, Math.round(scrollValue));
}

export function excludeElementScroll (element, point) {
    var isTextEditable = domUtils.isTextEditableElement(element);
    var isInputElement = domUtils.isInputElement(element);

    if (!(isTextEditable || domUtils.isContentEditableElement(element)))
        return point;

    var elementOffset  = positionUtils.getOffsetPosition(element);
    var elementBorders = styleUtils.getBordersWidth(element);
    var elementScroll  = styleUtils.getElementScroll(element);
    var maxLeft        = elementOffset.left + elementBorders.left + element.clientWidth;

    // NOTE: we can't know input elements' scroll value in Mozilla and
    // IE > 10 (https://bugzilla.mozilla.org/show_bug.cgi?id=293186)
    if (isInputElement && isTextEditable &&
        (browserUtils.isFirefox || browserUtils.isIE && browserUtils.version > 10)) {
        return {
            x: Math.min(point.x, maxLeft),
            y: point.y
        };
    }

    return {
        x: point.x - elementScroll.left,
        y: point.y - elementScroll.top
    };
}
<|endoftext|>


<commit_before>/**
* @fileoverview Interprets a given command and calls workspace controller_.functions.
* @author pandori@wisc.edu (Sahib Pandori)
* @author david.liang@wisc.edu (David Liang)
*/

'use strict';

goog.provide('SpeechBlocks.Interpreter');

goog.require('SpeechBlocks.Predecessor');
goog.require('SpeechBlocks.StatementInput')
goog.require('SpeechBlocks.Successor');
goog.require('SpeechBlocks.Translation');
goog.require('SpeechBlocks.ValueInput');
goog.require('goog.structs.Map');

/**
* Constructs an interpreter that takes actions as input and controls the Blockly Workspace.
* @param {!SpeechBlocks.Controller} controller_.The workspace controller_.
*/
SpeechBlocks.Interpreter = function(controller) {
  /** @private @const */
  this.controller_ = controller;
  /** @private */
  this.id_ = 1;
  /** @private */
  this.blockTypeMap_ = new goog.structs.Map();
  /**
  this.blockTypeMap_.set('if','controls_if');
  this.blockTypeMap_.set('comparison','logic_compare');
  this.blockTypeMap_.set('repeat','controls_repeat_ext');
  this.blockTypeMap_.set('number','math_number');
  this.blockTypeMap_.set('arithmetic','math_arithmetic');
  this.blockTypeMap_.set('text','text');
  this.blockTypeMap_.set('print','text_print');
  this.blockTypeMap_.set('set','variables_set');
  this.blockTypeMap_.set('variable','variables_get');
  */
  // temporary
  try {
    var rawFile = new XMLHttpRequest();
    rawFile.open("GET", 'https://aravart.github.io/speech-blocks/grammar/blockTypeMap.txt', true);
    rawFile.onreadystatechange = function () {
      console.log(rawFile.readyState);
      if(rawFile.readyState == 4) {
          console.log('b');
        if(rawFile.status == 200 || rawFile.status == 0) {
            console.log('c');
          var inputText = rawFile.responseText;
          inputText = inputText.split(/\r\n|\r|\n/g);
          for (var i = 0; i < inputText.length; i++) {
            var keyValuePair = inputText[i].split(":");
            console.log(keyValuePair[0]);
            console.log(keyValuePair[1]);
            this.blockTypeMap_.set(keyValuePair[0], keyValuePair[1]);
          }
          console.log(inputText);
        }
        rawFile.send();
      }
      rawFile.send();
    }
    rawFile.onreadystatechange();
  } catch(err) { console.log(err.message); }
  console.log(this.blockTypeMap_.isEmpty());
  console.log(this.blockTypeMap_.getValues())
  console.log(this.blockTypeMap_.get('if'));
}

/**
* Interprets a given command by calling the corresponding action function.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.interpret = function(command) {
  switch (command.action) {
    case 'run': this.run(command); break;
    case 'add': this.addBlock(command); break;
    case 'move': this.moveBlock(command); break;
    case 'modify': this.modifyBlock(command); break;
    case 'delete': this.deleteBlock(command); break;
    default: console.log('Unsupported command');
  }
};

/**
* Compiles the Blockly code into JavaScript and runs it.
* @param {Object=} command Object with command specifics from the parser.
*/
SpeechBlocks.Interpreter.prototype.run = function(command) {
  Blockly.JavaScript.addReservedWords('code');
  var code = Blockly.JavaScript.workspaceToCode(this.controller_.workspace);
  eval(code);
};

/**
* Adds a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.addBlock = function(command) {
  var type = this.blockTypeMap_.get(command.type);
  if (type != null) { this.controller_.addBlock(type, (this.id_++).toString(), new SpeechBlocks.Translation(0,0)); }
};

/**
* @TODO Implement error checking
* Moves a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.moveBlock = function(command) {
  // ensure these fields are strings, so validity checking works properly
  command.block = command.block.toString();
  command.where.block = command.where.block.toString();
  if (this.isBlockIdValid(command.block)) {
    if (command.where == 'trash') {
      this.deleteBlock(command.block);
    } else {
      if (this.isBlockIdValid(command.where.block)) {
        switch (command.where.position) {
          // modify these so the 'where' field is right
          case 'after': this.controller_.moveBlock(command.block, new SpeechBlocks.Successor(command.where.block)); break;
          case 'before': this.controller_.moveBlock(command.block, new SpeechBlocks.Predecessor(command.where.block)); break;
          case 'lhs': case 'rhs': case 'to the right of':
          var inputList_ = this.controller_.getBlockValueInputs(command.where.block);
          if (inputList_.length < 1) { console.log('NO VALUE INPUTS FOR SPECIFIED BLOCK'); }
          else if (command.where.position == 'rhs' || command.where.position == 'to the right of') { this.controller_.moveBlock(command.block, new SpeechBlocks.ValueInput(command.where.block, inputList_[inputList_.length-1]));	}
          else { this.controller_.moveBlock(command.block, new SpeechBlocks.ValueInput(command.where.block, inputList_[0])); }
          case 'inside':
          var statementList_ = this.controller_.getBlockStatementInputs(command.where.block);
          if (statementList_.length < 1) { console.log('NO STATEMENT INPUTS FOR SPECIFIED BLOCK'); }
          else { this.controller_.moveBlock(command.block, new SpeechBlocks.StatementInput(command.where.block, statementList_[statementList_.length-1])); }
          break;
          default:
          console.log('Unsupported position');
        }
      }
    }
  }
  else {
    console.log('Invalid block Id');
  }
};

/**
* @TODO Implement each case of property
* Modifies a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.modifyBlock = function(command) {
  if (this.isBlockIdValid(command.block)) {
    switch(command.property) {
      case 'number':
      command.value = Number(command.value);
      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'text':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'comparison':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'operation':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'name':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      default:
      console.log('Unsupported property');
    }
    console.log('MODIFY NOT YET SUPPORTED');
  }
  else {
    console.log('Invalid block Id');
  }
};

/**
* Delete a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.deleteBlock = function(blockId) {
  if (this.isBlockIdValid(blockId)) { this.controller_.removeBlock(blockId); }
  else { console.log('Invalid block Id'); }
};

/**
* Checks to see if a block Id is valid.
* @param {!String=} blockId as string.
*/
SpeechBlocks.Interpreter.prototype.isBlockIdValid = function(blockRequestId) {
  return this.controller_.getAllBlockIds().contains(blockRequestId);
}
<commit_msg>File IO testing<commit_after>/**
* @fileoverview Interprets a given command and calls workspace controller_.functions.
* @author pandori@wisc.edu (Sahib Pandori)
* @author david.liang@wisc.edu (David Liang)
*/

'use strict';

goog.provide('SpeechBlocks.Interpreter');

goog.require('SpeechBlocks.Predecessor');
goog.require('SpeechBlocks.StatementInput')
goog.require('SpeechBlocks.Successor');
goog.require('SpeechBlocks.Translation');
goog.require('SpeechBlocks.ValueInput');
goog.require('goog.structs.Map');

/**
* Constructs an interpreter that takes actions as input and controls the Blockly Workspace.
* @param {!SpeechBlocks.Controller} controller_.The workspace controller_.
*/
SpeechBlocks.Interpreter = function(controller) {
  /** @private @const */
  this.controller_ = controller;
  /** @private */
  this.id_ = 1;
  /** @private */
  this.blockTypeMap_ = new goog.structs.Map();
  /**
  this.blockTypeMap_.set('if','controls_if');
  this.blockTypeMap_.set('comparison','logic_compare');
  this.blockTypeMap_.set('repeat','controls_repeat_ext');
  this.blockTypeMap_.set('number','math_number');
  this.blockTypeMap_.set('arithmetic','math_arithmetic');
  this.blockTypeMap_.set('text','text');
  this.blockTypeMap_.set('print','text_print');
  this.blockTypeMap_.set('set','variables_set');
  this.blockTypeMap_.set('variable','variables_get');
  */
  // temporary
  try {
    var rawFile = new XMLHttpRequest();
    rawFile.open("GET", 'https://aravart.github.io/speech-blocks/grammar/blockTypeMap.txt', true);
    rawFile.onreadystatechange = function () {
      console.log(rawFile.readyState);
      if(rawFile.readyState == 4 && rawFile.status == 200) {
          console.log('b');
        if(rawFile.status == 200 || rawFile.status == 0) {
            console.log('c');
          var inputText = rawFile.responseText;
          inputText = inputText.split(/\r\n|\r|\n/g);
          for (var i = 0; i < inputText.length; i++) {
            var keyValuePair = inputText[i].split(":");
            console.log(keyValuePair[0]);
            console.log(keyValuePair[1]);
            this.blockTypeMap_.set(keyValuePair[0], keyValuePair[1]);
          }
          console.log(inputText);
        }
        rawFile.send();
      }
      rawFile.send();
    }
    rawFile.onreadystatechange();
  } catch(err) { console.log(err.message); }
  console.log(this.blockTypeMap_.isEmpty());
  console.log(this.blockTypeMap_.getValues())
  console.log(this.blockTypeMap_.get('if'));
}

/**
* Interprets a given command by calling the corresponding action function.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.interpret = function(command) {
  switch (command.action) {
    case 'run': this.run(command); break;
    case 'add': this.addBlock(command); break;
    case 'move': this.moveBlock(command); break;
    case 'modify': this.modifyBlock(command); break;
    case 'delete': this.deleteBlock(command); break;
    default: console.log('Unsupported command');
  }
};

/**
* Compiles the Blockly code into JavaScript and runs it.
* @param {Object=} command Object with command specifics from the parser.
*/
SpeechBlocks.Interpreter.prototype.run = function(command) {
  Blockly.JavaScript.addReservedWords('code');
  var code = Blockly.JavaScript.workspaceToCode(this.controller_.workspace);
  eval(code);
};

/**
* Adds a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.addBlock = function(command) {
  var type = this.blockTypeMap_.get(command.type);
  if (type != null) { this.controller_.addBlock(type, (this.id_++).toString(), new SpeechBlocks.Translation(0,0)); }
};

/**
* @TODO Implement error checking
* Moves a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.moveBlock = function(command) {
  // ensure these fields are strings, so validity checking works properly
  command.block = command.block.toString();
  command.where.block = command.where.block.toString();
  if (this.isBlockIdValid(command.block)) {
    if (command.where == 'trash') {
      this.deleteBlock(command.block);
    } else {
      if (this.isBlockIdValid(command.where.block)) {
        switch (command.where.position) {
          // modify these so the 'where' field is right
          case 'after': this.controller_.moveBlock(command.block, new SpeechBlocks.Successor(command.where.block)); break;
          case 'before': this.controller_.moveBlock(command.block, new SpeechBlocks.Predecessor(command.where.block)); break;
          case 'lhs': case 'rhs': case 'to the right of':
          var inputList_ = this.controller_.getBlockValueInputs(command.where.block);
          if (inputList_.length < 1) { console.log('NO VALUE INPUTS FOR SPECIFIED BLOCK'); }
          else if (command.where.position == 'rhs' || command.where.position == 'to the right of') { this.controller_.moveBlock(command.block, new SpeechBlocks.ValueInput(command.where.block, inputList_[inputList_.length-1]));	}
          else { this.controller_.moveBlock(command.block, new SpeechBlocks.ValueInput(command.where.block, inputList_[0])); }
          case 'inside':
          var statementList_ = this.controller_.getBlockStatementInputs(command.where.block);
          if (statementList_.length < 1) { console.log('NO STATEMENT INPUTS FOR SPECIFIED BLOCK'); }
          else { this.controller_.moveBlock(command.block, new SpeechBlocks.StatementInput(command.where.block, statementList_[statementList_.length-1])); }
          break;
          default:
          console.log('Unsupported position');
        }
      }
    }
  }
  else {
    console.log('Invalid block Id');
  }
};

/**
* @TODO Implement each case of property
* Modifies a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.modifyBlock = function(command) {
  if (this.isBlockIdValid(command.block)) {
    switch(command.property) {
      case 'number':
      command.value = Number(command.value);
      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'text':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'comparison':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'operation':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'name':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      default:
      console.log('Unsupported property');
    }
    console.log('MODIFY NOT YET SUPPORTED');
  }
  else {
    console.log('Invalid block Id');
  }
};

/**
* Delete a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.deleteBlock = function(blockId) {
  if (this.isBlockIdValid(blockId)) { this.controller_.removeBlock(blockId); }
  else { console.log('Invalid block Id'); }
};

/**
* Checks to see if a block Id is valid.
* @param {!String=} blockId as string.
*/
SpeechBlocks.Interpreter.prototype.isBlockIdValid = function(blockRequestId) {
  return this.controller_.getAllBlockIds().contains(blockRequestId);
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import autobind from 'core-decorators/es/autobind';
import { graphql } from 'react-apollo';
import { _listObjectsFromS3 } from '../../../graphql/upload';
import { Spinner } from '@blueprintjs/core';
import S3Explorer from '../../../../../lib/react/components/S3Explorer';
import RefreshBar from '../RefreshBar';

const QueryS3ObjectsParams = 'Name Prefix KeyCount Contents{Key LastModified Size} CommonPrefixes{Prefix}';

@graphql(_listObjectsFromS3(QueryS3ObjectsParams), { name: 'QueryS3Objects' })
@autobind
class S3ExplorerView extends React.Component {
	static propTypes = {
		shouldRefresh: PropTypes.bool.isRequired
	}

	navigateTo(Prefix) {
		return (e) => {
			this.props.QueryS3Objects.refetch({ Prefix });
		}
	}

	open(Key) {
		return (e) => {
			console.log(Key);
		}
	}

	render() {
		let content;

		if (this.props.QueryS3Objects.loading) {
			if (this.objects) {
				content = <S3Explorer root={'uploads/'} objects={this.objects} navigateTo={this.navigateTo} open={this.open} loading/>
			}
			else {
				content = (

						<Spinner/>

				);
			}
		}
		else {
			this.objects = this.props.QueryS3Objects._listObjectsFromS3
			content = (
				<S3Explorer root={'uploads/'} objects={this.props.QueryS3Objects._listObjectsFromS3}
					navigateTo={this.navigateTo} open={this.open}/>
			);
		}

		return (

AWS S3 uploads explorer

				<RefreshBar query={this.props.QueryS3Objects} shouldRefresh={this.props.shouldRefresh}/>
				{content}

		);
	}
}

export default S3ExplorerView;
<commit_msg>[FIX] Fix S3 explorer error when no permission given to view<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import autobind from 'core-decorators/es/autobind';
import { graphql } from 'react-apollo';
import { _listObjectsFromS3 } from '../../../graphql/upload';
import { Spinner } from '@blueprintjs/core';
import S3Explorer from '../../../../../lib/react/components/S3Explorer';
import RefreshBar from '../RefreshBar';
import ViewError from '../ViewError';

const QueryS3ObjectsParams = 'Name Prefix KeyCount Contents{Key LastModified Size} CommonPrefixes{Prefix}';

@graphql(_listObjectsFromS3(QueryS3ObjectsParams), { name: 'QueryS3Objects' })
@autobind
class S3ExplorerView extends React.Component {
	static propTypes = {
		shouldRefresh: PropTypes.bool.isRequired
	}

	navigateTo(Prefix) {
		return (e) => {
			this.props.QueryS3Objects.refetch({ Prefix });
		}
	}

	open(Key) {
		return (e) => {
			console.log(Key);
		}
	}

	render() {
		let content;
		if (this.props.QueryS3Objects.loading) {
			if (this.objects) {
				content = (
					<S3Explorer root={'uploads/'} objects={this.objects} navigateTo={this.navigateTo} open={this.open} loading/>
				);
			}
			else {
				content = (

						<Spinner/>

				);
			}
		}
		else {
			if (this.props.QueryS3Objects.error) {
				content = (
					<ViewError error={this.props.QueryS3Objects.error}/>
				);
			}
			else {
				this.objects = this.props.QueryS3Objects._listObjectsFromS3
				content = (
					<S3Explorer root={'uploads/'} objects={this.props.QueryS3Objects._listObjectsFromS3}
						navigateTo={this.navigateTo} open={this.open}/>
				);
			}
		}

		return (

AWS S3 uploads explorer

				<RefreshBar query={this.props.QueryS3Objects} shouldRefresh={this.props.shouldRefresh}/>
				{content}

		);
	}
}

export default S3ExplorerView;
<|endoftext|>


<commit_before>/**
 * Copyright 2013-present NightWorld.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var pg = require('pg'),
	model = module.exports,
	connString = process.env.DATABASE_URL;

/*
 * Required
 */

model.getAccessToken = function (bearerToken, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('SELECT access_token, client_id, expires, user_id FROM oauth_access_tokens ' +
				'WHERE access_token = $1', [bearerToken], function (err, result) {
			// This object will be exposed in req.oauth.token
			// The user_id field will be exposed in req.user (req.user = { id: "..." }) however if
			// an explicit user object is included (token.user, must include id) it will be exposed
			// in req.user instead
			callback(err, result.rowCount ? result.rows[0] : false);
			done();
		});
	});
};

model.getClient = function (clientId, clientSecret, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('SELECT client_id, client_secret, redirect_uri FROM oauth_clients WHERE ' +
				'client_id = $1 AND client_secret = $2', [clientId, clientSecret],
				function (err, result) {
			// This object will be exposed in req.oauth.client
			callback(err, result.rowCount ? result.rows[0] : false);
			done();
		});
	});
};

model.getRefreshToken = function (bearerToken, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('SELECT refresh_token, client_id, expires, user_id FROM oauth_refresh_tokens ' +
				'WHERE refresh_token = $1', [bearerToken], function (err, result) {
			// The returned user_id will be exposed in req.user.id
			callback(err, result.rowCount ? result.rows[0] : false);
			done();
		});
	});
};

// This will very much depend on your setup, I wouldn't advise doing anything exactly like this but
// it gives an example of how to use the method to resrict certain grant types
var authorizedClientIds = ['abc1', 'def2'];
model.grantTypeAllowed = function (clientId, grantType, callback) {
	if (grantType === 'password') {
		return callback(false, authorizedClientIds.indexOf(clientId.toLowerCase()) >= 0);
	}

	callback(false, true);
};

model.saveAccessToken = function (accessToken, clientId, userId, expires, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('INSERT INTO oauth_access_tokens(access_token, client_id, user_id, expires) ' +
				'VALUES ($1, $2, $3, $4)', [accessToken, clientId, userId, expires],
				function (err, result) {
			callback(err);
			done();
		});
	});
};

model.saveRefreshToken = function (refreshToken, clientId, userId, expires, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('INSERT INTO oauth_refresh_tokens(refresh_token, client_id, user_id, ' +
				'expires) VALUES ($1, $2, $3, $4)', [accessToken, clientId, userId, expires],
				function (err, result) {
			callback(err);
			done();
		});
	});
};

/*
 * Required to support password grant type
 */
model.getUser = function (username, password, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('SELECT id FROM users WHERE username = $1 AND password = $2', [username,
				password], function (err, result) {
			callback(err, result.rowCount ? result.rows[0] : false);
			done();
		});
	});
};
<commit_msg>Fix postgres example<commit_after>/**
 * Copyright 2013-present NightWorld.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var pg = require('pg'),
	model = module.exports,
	connString = process.env.DATABASE_URL;

/*
 * Required
 */

model.getAccessToken = function (bearerToken, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('SELECT access_token, client_id, expires, user_id FROM oauth_access_tokens ' +
				'WHERE access_token = $1', [bearerToken], function (err, result) {
			// This object will be exposed in req.oauth.token
			// The user_id field will be exposed in req.user (req.user = { id: "..." }) however if
			// an explicit user object is included (token.user, must include id) it will be exposed
			// in req.user instead
			callback(err, result.rowCount ? result.rows[0] : false);
			done();
		});
	});
};

model.getClient = function (clientId, clientSecret, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('SELECT client_id, client_secret, redirect_uri FROM oauth_clients WHERE ' +
				'client_id = $1 AND client_secret = $2', [clientId, clientSecret],
				function (err, result) {
			// This object will be exposed in req.oauth.client
			callback(err, result.rowCount ? result.rows[0] : false);
			done();
		});
	});
};

model.getRefreshToken = function (bearerToken, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('SELECT refresh_token, client_id, expires, user_id FROM oauth_refresh_tokens ' +
				'WHERE refresh_token = $1', [bearerToken], function (err, result) {
			// The returned user_id will be exposed in req.user.id
			callback(err, result.rowCount ? result.rows[0] : false);
			done();
		});
	});
};

// This will very much depend on your setup, I wouldn't advise doing anything exactly like this but
// it gives an example of how to use the method to resrict certain grant types
var authorizedClientIds = ['abc1', 'def2'];
model.grantTypeAllowed = function (clientId, grantType, callback) {
	if (grantType === 'password') {
		return callback(false, authorizedClientIds.indexOf(clientId.toLowerCase()) >= 0);
	}

	callback(false, true);
};

model.saveAccessToken = function (accessToken, clientId, userId, expires, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('INSERT INTO oauth_access_tokens(access_token, client_id, user_id, expires) ' +
				'VALUES ($1, $2, $3, $4)', [accessToken, clientId, userId, expires],
				function (err, result) {
			callback(err);
			done();
		});
	});
};

model.saveRefreshToken = function (refreshToken, clientId, userId, expires, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('INSERT INTO oauth_refresh_tokens(refresh_token, client_id, user_id, ' +
				'expires) VALUES ($1, $2, $3, $4)', [refreshToken, clientId, userId, expires],
				function (err, result) {
			callback(err);
			done();
		});
	});
};

/*
 * Required to support password grant type
 */
model.getUser = function (username, password, callback) {
	pg.connect(connString, function (err, client, done) {
		if (err) return callback(err);
		client.query('SELECT id FROM users WHERE username = $1 AND password = $2', [username,
				password], function (err, result) {
			callback(err, result.rowCount ? result.rows[0] : false);
			done();
		});
	});
};
<|endoftext|>