CartoDB/cartodb20

View on GitHub
lib/assets/javascripts/builder/components/dataset/dataset-base-view.js

Summary

Maintainability
B
4 hrs
Test Coverage
var _ = require('underscore');
var Backbone = require('backbone');
var CoreView = require('backbone/core-view');
var SQLNotifications = require('builder/sql-notifications');
var SQLUtils = require('builder/helpers/sql-utils');
var Notifier = require('builder/components/notifier/notifier');
var cdb = require('internal-carto.js');
var checkAndBuildOpts = require('builder/helpers/required-opts');

var REQUIRED_OPTS = [
  'configModel',
  'editorModel',
  'layerDefinitionModel',
  'querySchemaModel'
];

module.exports = CoreView.extend({

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

    this._clearSQLModel = new Backbone.Model({
      visible: false
    });

    this._sqlModel = this._layerDefinitionModel.sqlModel;

    this._SQL = new cdb.SQL({
      user: this._configModel.get('user_name'),
      sql_api_template: this._configModel.get('sql_api_template'),
      api_key: this._configModel.get('api_key')
    });

    this._codemirrorModel = new Backbone.Model({
      content: this._querySchemaModel.get('query'),
      readonly: false
    });

    this._applyButtonStatusModel = new Backbone.Model({
      loading: false
    });

    SQLNotifications.track(this);
  },

  _internalParseSQL: function (callbackAfterAlterSuccess) {
    var appliedQuery = this._querySchemaModel.get('query');
    var currentQuery = this._codemirrorModel.get('content');

    // Remove last character if it has ';'
    if (currentQuery && currentQuery.slice(-1) === ';') {
      currentQuery = currentQuery.slice(0, currentQuery.length - 1);
      this._codemirrorModel.set('content', currentQuery);
    }

    var isSameQuery = SQLUtils.isSameQuery(currentQuery, appliedQuery);
    var altersData = SQLUtils.altersData(currentQuery);

    if (currentQuery === '' || isSameQuery) {
      SQLNotifications.removeNotification();
      return false;
    }

    if (altersData) {
      SQLNotifications.showNotification({
        status: 'loading',
        info: _t('notifications.sql.alter-loading'),
        closable: false
      });

      this._applyButtonStatusModel.set('loading', true);

      this._sqlModel.set('content', currentQuery);

      this._SQL.execute(currentQuery, null, {
        success: function () {
          SQLNotifications.showNotification({
            status: 'success',
            info: _t('notifications.sql.alter-success'),
            closable: true,
            delay: Notifier.DEFAULT_DELAY
          });

          this._applyButtonStatusModel.set('loading', false);

          this._applyDefaultSQLAfterAlteringData();

          if (typeof callbackAfterAlterSuccess === 'function') {
            callbackAfterAlterSuccess.call(this);
          }
        }.bind(this),
        error: function (errors) {
          var parsedErrors = this._parseErrors(errors.responseJSON && errors.responseJSON.error);

          this._applyButtonStatusModel.set('loading', false);

          this._codemirrorModel.set('errors', parsedErrors);

          SQLNotifications.showErrorNotification(parsedErrors);

          this._checkClearButton();
        }.bind(this)
      });
    } else {
      this._runQuery(currentQuery, this._saveSQL.bind(this));
    }
  },

  _checkClearButton: function () {
    var customSql = this._codemirrorModel.get('content');
    var isDefaultQuery = SQLUtils.isSameQuery(customSql, this._defaultSQL());
    this._clearSQLModel.set({ visible: !isDefaultQuery });
  },

  _applyDefaultSQLAfterAlteringData: function () {
    var originalQuery = this._defaultSQL();
    this._codemirrorModel.set({
      content: originalQuery,
      errors: []
    });
    this._sqlModel.set('content', originalQuery);
    this._querySchemaModel.set('query_errors', []);
    this._clearSQLModel.set({ visible: false });
    this._querySchemaModel.resetDueToAlteredData();
    this._clearSQL();
  },

  _clearSQL: function () {
    var originalQuery = this._defaultSQL();
    this._codemirrorModel.set({
      content: originalQuery,
      errors: []
    });
    this._runQuery(originalQuery, this._saveSQL.bind(this));
  },

  _showErrors: function (model) {
    var errors = this._querySchemaModel.get('query_errors');
    this._forceErrors(errors);
    this._checkClearButton();
  },

  _forceErrors: function (errors, options) {
    var hasErrors = errors && errors.length > 0;
    var parsedErrors = hasErrors && this._parseErrors(errors);
    var editorErrors = options && options.showEditorError === false ? [] : parsedErrors;
    this._codemirrorModel.set('errors', editorErrors);
    this._editorModel.set('disabled', hasErrors);

    if (hasErrors) {
      SQLNotifications.showErrorNotification(parsedErrors);
    }
  },

  _parseErrors: function (errors) {
    if (!errors) {
      return [];
    }

    errors = _.isArray(errors) ? errors : [errors];
    return errors.map(function (error) {
      return {
        message: error
      };
    });
  }
});