CartoDB/cartodb20

View on GitHub
lib/assets/javascripts/builder/components/modals/add-layer/add-layer-model.js

Summary

Maintainability
D
1 day
Test Coverage
var Backbone = require('backbone');
var UploadModel = require('builder/data/upload-model');
var VisualizationFetchModel = require('builder/data/visualizations-fetch-model');
var TablesCollection = require('builder/data/visualizations-collection');
var TableModel = require('builder/data/table-model');

var MetricsTracker = require('builder/components/metrics/metrics-tracker');
var MetricsTypes = require('builder/components/metrics/metrics-types');

var checkAndBuildOpts = require('builder/helpers/required-opts');

var UPLOAD = 'upload';
var IMPORT = 'import';
var DATASETS = 'datasets';
var SCRATCH = 'scratch';

var IMPORT_FILE = 'file';
var IMPORT_TWITTER = 'twitter';

var REQUIRED_OPTS = [
  'userModel',
  'userActions',
  'configModel',
  'pollingModel'
];

/**
 * Add layer model
 *
 * "Implements" the CreateListingModel.
 */
module.exports = Backbone.Model.extend({
  defaults: {
    type: 'addLayer',
    contentPane: 'listing', // [listing, loading]
    listing: DATASETS, // [UPLOAD, IMPORT, DATASETS, SCRATCH]
    collectionFetched: false,
    activeImportPane: IMPORT_FILE,
    navigationVisible: true
  },

  initialize: function (attrs, opts) {
    checkAndBuildOpts(opts, REQUIRED_OPTS, this);

    this._initModels();
    this._initBinds();
    this._fetchCollection();
  },

  _initModels: function () {
    this._uploadModel = new UploadModel({
      create_vis: false
    }, {
      userModel: this._userModel,
      configModel: this._configModel
    });

    this._selectedDatasetsCollection = new Backbone.Collection();

    this._tablesCollection = new TablesCollection([], {
      configModel: this._configModel
    });

    this._visualizationFetchModel = new VisualizationFetchModel({
      content_type: DATASETS,
      library: this.showLibrary()
    });
  },

  getTablesCollection: function () {
    return this._tablesCollection;
  },

  getSelectedDatasetsCollection: function () {
    return this._selectedDatasetsCollection;
  },

  getVisualizationFetchModel: function () {
    return this._visualizationFetchModel;
  },

  getUploadModel: function () {
    return this._uploadModel;
  },

  canSelect: function (dataset) {
    return dataset.get('selected') || this._selectedDatasetsCollection.length < 1; // for now only allow 1 item
  },

  showLibrary: function () {
    return false;
  },

  showDatasets: function () {
    return true;
  },

  setActiveImportPane: function (name) {
    this.set('activeImportPane', name);
  },

  canFinish: function () {
    if (this._atAnyImportPane()) {
      return this._uploadModel.isValidToUpload();
    } else if (this._atDatasetsPane()) {
      return this._selectedDatasetsCollection.length > 0;
    }
  },

  finish: function () {
    if (this._atAnyImportPane()) {
      this._pollingModel.trigger('importByUploadData', this._uploadModel.toJSON(), this);
    } else if (this._atDatasetsPane()) {
      var mdl = this._selectedDatasetsCollection.at(0);
      if (mdl.get('type') === 'remote') {
        var d = {
          create_vis: false,
          type: 'remote',
          value: mdl.get('name'),
          remote_visualization_id: mdl.get('id'),
          size: mdl.get('external_source') ? mdl.get('external_source').size : undefined
        };
        // See BackgroundImporter where the same event is bound to be handled..
        this._pollingModel.trigger('importByUploadData', d, this);
      } else {
        this._addNewLayer(mdl.getTableModel());
      }
    }
  },

  getImportState: function () {
    return this.get('activeImportPane');
  },

  showGuessingToggler: function () {
    return this._atAnyImportPane();
  },

  showPrivacyToggler: function () {
    var hiddenDueToDeprecation = this._atTwitterImportPane() && !this._userModel.hasOwnTwitterCredentials();
    var hasToBeShowed = this._atAnyImportPane() && !hiddenDueToDeprecation;
    return hasToBeShowed;
  },

  // Both panes import data
  _atAnyImportPane: function () {
    return this._atImportPane() || this._atUploadPane();
  },

  _atUploadPane: function () {
    return this.get('listing') === UPLOAD;
  },

  _atImportPane: function () {
    return this.get('listing') === IMPORT;
  },

  _atDatasetsPane: function () {
    return this.get('listing') === DATASETS;
  },

  _atScratchPane: function () {
    return this.get('listing') === SCRATCH;
  },

  _atTwitterImportPane: function () {
    return this.get('activeImportPane') === IMPORT_TWITTER;
  },

  createFromScratch: function () {
    var self = this;
    this.set('contentPane', 'creatingFromScratch');
    var tableModel = new TableModel({}, {
      configModel: this._configModel
    });
    tableModel.save({}, {
      success: function () {
        self._addNewLayer(tableModel, true);
      },
      error: function (req, resp) {
        if (resp.responseText.indexOf('You have reached your table quota') !== -1) {
          self.set('contentPane', 'datasetQuotaExceeded');
        } else {
          self.set('contentPane', 'addLayerFailed');
        }
      }
    });
  },

  _initBinds: function () {
    this._uploadModel.bind('change', function () {
      this.trigger('change:upload', this);
    }, this);
    this._visualizationFetchModel.bind('change', this._fetchCollection, this);
    this.bind('change:listing', this._fetchCollection, this);

    this._tablesCollection.bind('change:selected', function (changedModel, wasSelected) {
      this._selectedDatasetsCollection[wasSelected ? 'add' : 'remove'](changedModel);
    }, this);
    this._tablesCollection.bind('sync', function () {
      this._selectedDatasetsCollection.each(function (model) {
        var sameModel = this._tablesCollection.get(model.id);
        if (sameModel) {
          sameModel.set('selected', true);
        }
      }, this);
    }, this);
  },

  _fetchCollection: function () {
    var params = this._visualizationFetchModel.attributes;
    var types;

    if (this._visualizationFetchModel.isSearching()) {
      // Supporting search in data library and user datasets at the same time
      types = 'table,remote';
    } else {
      types = params.library ? 'remote' : 'table';
    }

    this._tablesCollection.fetch({
      data: {
        locked: '',
        q: params.q,
        page: params.page,
        tags: params.tag,
        shared: params.shared,
        only_liked: params.liked,
        type: '',
        types: types
      }
    });
  },

  _onCollectionChange: function () {
    this._selectedDatasetsCollection.reset(
      this._tablesCollection.where({ selected: true })
    );
  },

  _addNewLayer: function (tableModel, empty) {
    this.set('contentPane', 'addingNewLayer');

    this._userActions.createLayerFromTable(tableModel, {
      success: function (model) {
        this._userModel.updateTableCount();
        this.trigger('addLayerDone');
        MetricsTracker.track(MetricsTypes.CREATED_LAYER, {
          empty: !!empty,
          layer_id: model.get('id')
        });
      }.bind(this),
      error: function (req, resp) {
        if (resp.responseText.indexOf('You have reached your table quota') !== -1) {
          this.set('contentPane', 'datasetQuotaExceeded');
        } else {
          this.set('contentPane', 'addLayerFailed');
        }
      }.bind(this)
    });
  }
});