render: function() {
    var processedRows = this.model.get('processed_rows') || 0;
    var processableRows = this.model.get('processable_rows') || 0;
    var realRows = this.model.get('real_rows') || 0;
    var isLatLngType = this.model.get('latitude_column') && this.model.get('longitude_column');

    var d = {
      realRows: realRows,
      tableName: this.model.get('table_name'),
      canCancel: _.isFunction(this.model.cancelGeocoding),
      hasFailed: this.model.hasFailed(),
      hasCompleted: this.model.hasCompleted(),
      processedRows: processedRows,
      processableRows: processableRows,
      processableRowsFormatted: Utils.formatNumber(processableRows),
      realRowsPluralize: pluralizeString('row', 'rows', this.model.get('real_rows')),
      realRowsFormatted: Utils.formatNumber(realRows),
      processableRowsPluralize: pluralizeString('row', 'rows', processableRows),
      width: realRows > 0 ? (processableRows/realRows) : 100,
      isLatLngType: isLatLngType
    }
    this.$el.html(this.template(d));

    return this;
  },
Example #2
0
  render: function() {
    var vis = this.model;
    var user = this.user;
    var table = vis.tableMetadata();
    var isOwner = vis.permission.isOwner(user);
    var tags = vis.get('tags') || [];
    var desc = {
      safeHTML: cdb.core.sanitize.html(markdown.toHTML(vis.get('description') || ''))
    };
    desc.clean = cdb.Utils.stripHTML(desc.safeHTML);

    var d = {
      isRaster:                vis.get('kind') === 'raster',
      geometryType:            table.statsGeomColumnTypes().length > 0 ? table.statsGeomColumnTypes()[0] : '',
      title:                   vis.get('name'),
      datasetUrl:              encodeURI(vis.viewUrl(this.user).edit()),
      isOwner:                 isOwner,
      owner:                   vis.permission.owner.renderData(this.user),
      showPermissionIndicator: !isOwner && vis.permission.getPermission(user) === cdb.admin.Permission.READ_ONLY,
      desc:                    desc,
      privacy:                 vis.get('privacy').toLowerCase(),
      likes:                   vis.get('likes') || 0,
      timeDiff:                moment(vis.get('updated_at')).fromNow(),
      tags:                    tags,
      tagsCount:               tags.length,
      router:                  this.router,
      maxTagsToShow:           3,
      rowCount:                undefined,
      datasetSize:             undefined,
      syncStatus:              undefined,
      syncRanAt:               undefined
    };

    var rowCount = table.get('row_count');
    if (rowCount >= 0) {
      d.rowCount = ( rowCount < 10000 ? Utils.formatNumber(rowCount) : Utils.readizableNumber(rowCount) );
      d.pluralizedRows = pluralizeString('Row', rowCount);
    }

    var datasetSize = table.get('size');
    if (datasetSize >= 0) {
      d.datasetSize = Utils.readablizeBytes(datasetSize, true);
    }

    if (!_.isEmpty(vis.get("synchronization"))) {
      d.syncRanAt = moment(vis.get("synchronization").ran_at || new Date()).fromNow();
      d.syncStatus = vis.get("synchronization").state;
    }

    this.$el.html(this.template(d));

    this._renderLikesIndicator();
    this._renderTooltips();

    // Item selected?
    this.$el[ vis.get('selected') ? 'addClass' : 'removeClass' ]('is--selected');

    return this;
  },
  render_content: function() {
    var error = this.model.get('error') || {};

    var processedRows = this.model.get('processed_rows') || 0;
    var processableRows = this.model.get('processable_rows') || 0;
    var realRows = this.model.get('real_rows') || 0;
    var geometryType = this.model.get('geometry_type') || 'point';

    // Related to price and credits
    var price = this.model.get('price');
    var hasPrice = price !== undefined && price !== null;
    var googleUser = this.user.featureEnabled('google_maps');

    var datasetURL;
    if (this.user && this.model.get('table_name')) {
      var vis = new cdb.admin.Visualization({
        type: 'table',
        table: {
          name: this.model.get('table_name')
        }
      });
      vis.permission.owner = this.user;
      datasetURL = encodeURI(vis.viewUrl(this.user).edit());
    }

    // Select template
    var template = 'common/background_polling/views/geocodings/';
    if (this.model.hasCompleted()) {
      template += realRows === 0 ? 'geocoding_no_result_details' : 'geocoding_success_details';
    } else {
      template += 'geocoding_error_details';
    }

    return cdb.templates.getTemplate(template)({
      id: this.model.get('id'),
      geometryTypePluralize: pluralizeString(geometryType, geometryType + 's', processableRows),
      geometryType: geometryType,
      remainingQuotaFormatted: Utils.formatNumber(this.model.get('remaining_quota')),
      googleUser: googleUser,
      tableName: this.model.get('table_name'),
      state: this.model.get('state') || '',
      blockPrice: this.user.get('geocoding').block_price,
      realRows: realRows,
      realRowsFormatted: Utils.formatNumber(realRows),
      processedRows: processedRows,
      processableRows: processableRows,
      processableRowsFormatted: Utils.formatNumber(processableRows),
      hasPrice: hasPrice,
      price: price,
      customHosted: cdb.config.get('cartodb_com_hosted'),
      errorDescription: error.description,
      showGeocodingDatasetURLButton: this.options.showGeocodingDatasetURLButton && datasetURL,
      datasetURL: datasetURL
    });
  }
Example #4
0
  render: function() {
    var vis = this.model;
    var table = this.table;
    var tags = vis.get('tags') || [];
    var description = vis.get('description') && Utils.stripHTML(markdown.toHTML(vis.get('description'))) || '';

    var d = {
      isRaster:                vis.get('kind') === 'raster',
      geometryType:            table.geomColumnTypes().length > 0 ? table.geomColumnTypes()[0] : '',
      title:                   vis.get('name'),
      isOwner:                 vis.permission.isOwner(this.user),
      owner:                   vis.permission.owner.renderData(this.user),
      showPermissionIndicator: !vis.permission.hasWriteAccess(this.user),
      description:             description,
      privacy:                 vis.get('privacy').toLowerCase(),
      likes:                   vis.get('likes') || 0,
      timeDiff:                moment(vis.get('updated_at')).fromNow(),
      tags:                    tags,
      tagsCount:               tags.length,
      maxTagsToShow:           3,
      rowCount:                undefined,
      datasetSize:             undefined,
      syncStatus:              undefined,
      syncRanAt:               undefined
    };

    var rowCount = table.get('row_count');
    if (rowCount >= 0) {
      d.rowCount = ( rowCount < 10000 ? Utils.formatNumber(rowCount) : Utils.readizableNumber(rowCount) );
      d.pluralizedRows = pluralizeString('Row', rowCount);
    }

    var datasetSize = table.get('size');
    if (datasetSize >= 0) {
      d.datasetSize = Utils.readablizeBytes(datasetSize, true);
    }

    if (!_.isEmpty(vis.get("synchronization"))) {
      d.syncRanAt = moment(vis.get("synchronization").ran_at || new Date()).fromNow();
      d.syncStatus = vis.get("synchronization").state;
    }

    this.$el.html(this.template(d));

    this._renderLikesIndicator();
    this._renderTooltips();

    // Item selected?
    this.$el[ vis.get('selected') ? 'addClass' : 'removeClass' ]('is--selected');

    return this;
  },
 var availablePlans = _.compact(this.collection.map(function(plan) {
   if (plan.get('price') === 0) {
     return false;
   } else {
     return {
       name: plan.get('title').toLowerCase(),
       price: Utils.formatNumber(plan.get('price')),
       quota: Utils.readablizeBytes(plan.get('bytes_quota')).replace(/\.00/g,''),
       layers: plan.get('max_layers'),
       privateMaps: plan.get('private_tables'),
       removableBrand: plan.get('removable_brand')
     }
   }
 }));
  render: function() {
    var vis = this.model;
    var table = this.table;
    var tags = vis.get('tags') || [];
    var description = vis.get('description') && Utils.stripHTML(markdown.toHTML(vis.get('description'))) || '';
    var source = vis.get('source') && markdown.toHTML(vis.get('source')) || '';

    var d = {
      isRaster:                vis.get('kind') === 'raster',
      geometryType:            table.statsGeomColumnTypes().length > 0 ? table.statsGeomColumnTypes()[0] : '',
      title:                   vis.get('display_name') || vis.get('name'),
      source:                  source,
      description:             description,
      timeDiff:                moment(vis.get('updated_at')).fromNow(),
      tags:                    tags,
      tagsCount:               tags.length,
      router:                  this.router,
      maxTagsToShow:           3,
      canImportDataset:        this._canImportDataset(),
      rowCount:                undefined,
      datasetSize:             undefined,
      fromExternalSource:      ""
    };

    var rowCount = table.get('row_count');
    if (rowCount >= 0) {
      d.rowCount = ( rowCount < 10000 ? Utils.formatNumber(rowCount) : Utils.readizableNumber(rowCount) );
      d.pluralizedRows = pluralizeString('Row', rowCount);
    }

    if (!_.isEmpty(vis.get("synchronization"))) {
      d.fromExternalSource = vis.get("synchronization").from_external_source;
    }

    var datasetSize = table.get('size');
    if (datasetSize >= 0) {
      d.datasetSize = Utils.readablizeBytes(
        datasetSize,
        datasetSize.toString().length > 9 ? false : true
      );
    }

    this.$el.html(this.template(d));
    this._setItemClasses();
    this._renderTooltips();

    return this;
  },
  render: function() {
    var title = this.options.fileAttrs.title && this.model.get('value')[this.options.fileAttrs.title] || this.model.get('value');
    var description = this._genDescription();
    var ext = this.options.fileAttrs.ext ? Utils.getFileExtension(title) : '' ;

    if (this.options.fileAttrs.ext) {
      title = title && title.replace('.' + ext, '');
    }

    var upgradeUrl = window.upgrade_url;
    var userCanSync = this.user.get('actions') && this.user.get('actions').sync_tables;
    var customInstall = cdb.config.get('cartodb_com_hosted');

    this.$el.html(
      this.template({
        title: title,
        description: description,
        ext: ext,
        interval: this.model.get('interval'),
        importCanSync: this.options.acceptSync && this._isArcGISLayer(title),
        userCanSync: userCanSync,
        showUpgrade: !userCanSync && !customInstall && upgradeUrl && !this.user.isInsideOrg(),
        upgradeUrl: upgradeUrl
      })
    );
    return this;
  },
 _submitSearch: function(e) {
   var search = this._$searchInput().val().trim();
   this.pagedSearchModel.set({
     q: Utils.stripHTML(search),
     page: 1
   })
   this.pagedSearchModel.fetch(this.organizationUsers);
 },
Example #9
0
var _parseDescription = function (author, description) {
  var createdByAuthor = _t('helpers.static_header_meta_tags.map_created_by', {
    author: author
  });

  return description
    ? Utils.stripHTML(markdown.toHTML(description)) + ' — ' + createdByAuthor
    : createdByAuthor;
}
Example #10
0
  render: function() {
    var twitterData = this.user.get('twitter');
    var remaining = twitterData.quota - twitterData.monthly_use;
    var per = Math.min(100,Math.ceil((this.model.get('value') * 100) / remaining));

    this.$el.html(
      this.template({
        value: this.model.get('value'),
        remaining: remaining,
        per: per,
        remainingFormatted: Utils.formatNumber(remaining),
        quota: twitterData.quota,
        block_price: twitterData.block_price,
        block_size: Utils.readizableNumber(twitterData.block_size)
      })
    )
    return this;
  },
 _submitSearch: function(e) {
   var search = this.$('.js-search-input').val().trim();
   this.organizationUsers
     .setParameters({
       q: Utils.stripHTML(search),
       page: 1
     })
     .fetch();
 },
Example #12
0
 _submitSearch: function(e) {
   this.killEvent(e);
   this._navigateToUrl({
     search: Utils.stripHTML(this.$('.js-search-input').val().trim(),''),
     liked: false,
     shared: 'no',
     library: false
   });
 },
Example #13
0
  _submitSearch: function(e) {
    this.killEvent(e);

    this.model.set('is_searching', true);

    this.collection.options.set({
      q: Utils.stripHTML(this.$('.js-search-input').val().trim(),''),
      page: 1
    });

    this.render();
  },
  _getInfo: function () {
    var processedRows = this._importModel.get('processed_rows') || 0;
    var processableRows = this._importModel.get('processable_rows') || 0;
    var realRows = this._importModel.get('real_rows') || 0;
    var isLatLngType = this._importModel.get('latitude_column') && this._importModel.get('longitude_column');

    var d = {
      realRows: realRows,
      tableName: this._importModel.get('table_name'),
      canCancel: _.isFunction(this._importModel.cancelGeocoding),
      hasFailed: this._importModel.hasFailed(),
      hasCompleted: this._importModel.hasCompleted(),
      processedRows: processedRows,
      processableRows: processableRows,
      processableRowsFormatted: Utils.formatNumber(processableRows),
      realRowsFormatted: Utils.formatNumber(realRows),
      width: realRows > 0 ? (processableRows / realRows).toFixed(0) : 100,
      isLatLngType: isLatLngType
    };

    return template(d);
  },
  render: function() {
    var userQuota = this.model.get('userQuota');
    var orgQuota = this.model.get('orgQuota');
    var assignedPer = (userQuota * 100) / orgQuota;

    // Edit assigned bar
    this.$('.js-assignedBar').css('width', assignedPer + '%' );

    // Edit assigned literal
    this.$('.js-assignedSize').text(Utils.readablizeBytes(userQuota));

    return this;
  },
  render: function() {
    this.$el.html(
      this.template({
        totalPer: this.options.totalPer,
        userPer: this.options.userPer,
        usedPer: this.options.usedPer,
        isOwner: this.options.isOwner,
        url: this.options.url,
        sizeOnBytes: Utils.readablizeBytes(this.model.get('db_size_in_bytes')),
        quotaInBytes: Utils.readablizeBytes(this.model.get('quota_in_bytes')),
        avatarUrl: this.model.get('avatar_url'),
        username: this.model.get('username'),
        user_email: this.model.get('email'),
        table_count: pluralizeStr.prefixWithCount('Dataset', 'Datasets', this.model.get('table_count')),
        maps_count: pluralizeStr.prefixWithCount('Map', 'Maps', this.model.get('all_visualization_count'))
      })
    );

    this._initViews();

    return this;
  },
Example #17
0
  _submitSearch: function(e) {
    if (e) this.killEvent(e);
    var val = Utils.stripHTML(this.$('.js-search-input').val().trim(),'');
    var tag = val.search(':') === 0 ? val.replace(':', '') : '';
    var q = val.search(':') !== 0 ? val : '';

    this.routerModel.set({
      tag: tag,
      q: q,
      shared: 'yes'
    });

    this.createModel.set('listing', 'datasets');
  }
  render: function () {
    var baseUrl = this.user.get('base_url');
    var createdByInfo = 'Map created by ' + this.user.get('username') + ' in CARTO';
    var description = this.vizdata.description
      ? Utils.stripHTML(markdown.toHTML(this.vizdata.description) + ' ' + createdByInfo)
      : createdByInfo;

    var encodedName = window.encodeURI(this.vizdata.name);
    var encodedUrl = window.encodeURI(baseUrl + '/viz/' + this.vizdata.id + '/public_map');
    var encodedDescription = window.encodeURI(description);

    this.clearSubViews();

    this.$el.html(this.template({
      baseUrl: baseUrl,
      editUrl: baseUrl + '/viz/' + this.vizdata.id + '/map',
      embedMapUrl: baseUrl + '/viz/' + this.vizdata.id + '/embed_map',
      likesCount: this.likeModel.get('likes'),
      likeURL: this.likeURL,
      liked: this.likeModel.get('liked'),
      shareFacebook: encodedUrl,
      shareLinkedIn: encodedUrl + '&title=' + encodedName + '&summary=' + encodedDescription + '&source=CARTO',
      shareTwitter: encodedName + '&url=' + encodedUrl + '&via=CARTO',
      userAvatar: this.user.get('avatar_url'),
      userName: this.user.nameOrUsername(),
      vizId: this.vizdata.id
    }));

    if (this.currentUser && this.currentUser.get('username') === this.user.get('username')) {
      this.$('.js-Navmenu-editLink').addClass('is-active');
    }

    this.userShareView = new UserShareView({
      el: this.$('.js-Navmenu-share'),
      model: new cdb.core.Model({
        active: false
      })
    });
    this.addView(this.userShareView);

    this.likesView = new cdb.open.LikeView({
      el: this.$('.js-like'),
      auto_fetch: true,
      model: this.likeModel
    });
    this.addView(this.likesView);

    return this;
  },
Example #19
0
  _changeRouteToTag: function(contentType, tag, page) {
    page = this._getPage(page);

    this.model.set({
      action:         'tag',
      content_type:   contentType,
      tag:            Utils.stripHTML(decodeURIComponent(tag),''),
      q:              '',
      page:           page,
      shared:         'yes',
      locked:         null,
      liked:          null,
      library:        null
    });
  },
Example #20
0
  _changeRouteToSearch: function(contentType, q, page) {
    page = this._getPage(page);

    this.model.set({
      action:         'search',
      content_type:   contentType,
      q:              Utils.stripHTML(decodeURIComponent(q),''),
      tag:            '',
      page:           page,
      shared:         'yes',
      locked:         null,
      liked:          null,
      library:        null,
      deepInsights:   false
    });
  },
 beforeTagAdded: function(ev, ui) {
   var value = ui.tagLabel;
   self._removeSubmitError();
   
   // It is an email
   if (!Utils.isValidEmail(value)) {
     return false;
   }
   // It is already in the organization
   if (_.contains(organizationUsersEmail, value)) {
     self._toggleEmailError(true);
     return false;
   } else {
     self._toggleEmailError(false);
   }
 },
  render: function() {
    var title = this.model.get(this.options.fileAttrs.title);
    var description = this._genDescription();
    var ext = this.options.fileAttrs.ext ? Utils.getFileExtension(title) : '' ;

    if (this.options.fileAttrs.ext) {
      title = title && title.replace('.' + ext, '');
    }

    this.$el.html(
      this.template({
        name: this.options.title,
        ext: ext,
        title: title,
        description: description
      })
    );
    return this;
  },
 render_content: function() {
   var imp = this.model.get('import');
   var userTwitterValues = this.user.get('twitter');
   var availableTweets = userTwitterValues.quota - userTwitterValues.monthly_use;
   var d = {
     datasetTotalRows: imp.tweets_georeferenced,
     datasetTotalRowsFormatted: Utils.formatNumber(imp.tweets_georeferenced),
     tweetsCost: imp.tweets_cost,
     tweetsCostFormatted: Utils.formatNumber(imp.tweets_cost),
     availableTweets: availableTweets,
     availableTweetsFormatted: Utils.formatNumber(availableTweets),
     tweetsOverquota: imp.tweets_overquota,
     tweetsOverquotaFormatted: Utils.formatNumber(imp.tweets_overquota),
     blockSizeFormatted: Utils.formatNumber(userTwitterValues.block_size),
     blockPriceFormatted: Utils.formatNumber(userTwitterValues.block_price)
   };
   return this.template(d);
 }
Example #24
0
  render: function() {
    var src = this.options.url + "?api_key=" + this.options.api_key;

    var wizardName = this.model.get("visualizationType").charAt(0).toUpperCase() + this.model.get("visualizationType").slice(1);

    var null_count = +(this.model.get("null_ratio") * this.model.get("count")).toFixed(2);
    var prettyNullCount = Utils.formatNumber(null_count);

    this.$el.html(
      this.template({
      column: this.model.get("column"),
      wizard: wizardName,
      metadata: this.model.get("metadata"),
      null_count: prettyNullCount,
      weight: this.model.get("weight")
    }));

    if (this.model.get("visualizationType") === "choropleth") {
      this._addHistogram();
    }

    var self = this;
    var img = new Image();
    img.onerror = function() {
      cdb.log.info("error loading the image for " + self.model.get("column"));
    };
    img.onload = function() {
      self.$(".js-loader").hide();
      self.$(".js-header").append('<img class="MapCard-preview" src="' + src + '" />');
      self.$("img").show();
    };

    img.src = src;

    return this;
  },
 render_content: function() {
   var imp = this.model.get('import');
   var userTwitterValues = this.user.get('twitter');
   var availableTweets = userTwitterValues.quota - userTwitterValues.monthly_use;
   var vis = this.model.importedVis();
   var url = vis && encodeURI(vis.viewUrl(this.user).edit()) || '';
   var d = {
     type: vis && vis.get('type') === "table" ? "dataset" : "map",
     mapURL: url,
     datasetTotalRows: imp.tweets_georeferenced,
     datasetTotalRowsFormatted: Utils.formatNumber(imp.tweets_georeferenced),
     tweetsCost: imp.tweets_cost,
     tweetsCostFormatted: Utils.formatNumber(imp.tweets_cost),
     availableTweets: availableTweets,
     availableTweetsFormatted: Utils.formatNumber(availableTweets),
     tweetsOverquota: imp.tweets_overquota,
     tweetsOverquotaFormatted: Utils.formatNumber(imp.tweets_overquota),
     blockSizeFormatted: Utils.formatNumber(userTwitterValues.block_size),
     blockPriceFormatted: Utils.formatNumber(userTwitterValues.block_price)
   };
   return this.template(d);
 }
Example #26
0
 .attr('data-title', function(d) {
   return Utils.formatNumber(d[1])
 })
Example #27
0
  validate: function(attrs) {
    if (!attrs) return;

    if (attrs.type === "file") {
      // Number of files
      if (attrs.value && attrs.value.length) {
        return {
          msg: "Unfortunately only one file is allowed per upload"
        }
      }

      // File name
      var name = attrs.value.name;
      if (!name) {
        return {
          msg: "File name should be defined"
        }
      }

      // File extension
      var ext = name.substr(name.lastIndexOf('.') + 1);
      if (ext) {
        ext = ext.toLowerCase();
      }
      if (!_.contains(UploadConfig.fileExtensions, ext)) {
        return {
          msg: "Unfortunately this file extension is not allowed"
        }
      }
      // File size
      if (this.user && ((this.user.get('remaining_byte_quota') * UploadConfig.fileTimesBigger) < attrs.value.size)) {
        return {
          msg: "Unfortunately the size of the file is bigger than your remaining quota",
          error_code: 8001
        }
      }
    }

    if (attrs.type === "remote") {
      // Valid remote visualization id?
      if (!attrs.remote_visualization_id) {
        return {
          msg: "The remote visualization id was not specified"
        }

      }
      // Remote size?
      if (this.user && attrs.size && ((this.user.get('remaining_byte_quota') * UploadConfig.fileTimesBigger) < attrs.size)) {
        return {
          msg: "Unfortunately the size of the remote dataset is bigger than your remaining quota",
          error_code: 8001
        }
      }
    }

    if (attrs.type === "url") {
      // Valid URL?
      if (!Utils.isURL(attrs.value)) {
        return {
          msg: "Unfortunately the URL provided is not valid"
        }
      }
    }

    if (attrs.type === "sql") {
      if (!attrs.value) {
        return {
          msg: "Query is not provided"
        }
      }
    }

    if (attrs.type === "duplication") {
      if (!attrs.value) {
        return {
          msg: "Dataset copy is not defined"
        }
      }
    }

    if (attrs.type === "service" && attrs.service_name === "twitter_search") {
      var service_item_id = attrs.service_item_id;

      // Empty?
      if (!service_item_id || _.isEmpty(service_item_id)) {
        return {
          msg: "Twitter data is empty"
        }
      }

      // Categories?
      if (_.isEmpty(service_item_id.categories)) {
        return {
          msg: "Twitter categories are not valid"
        }
      }

      // Dates?
      var dates = service_item_id.dates;
      if (!dates || _.isEmpty(dates)) {
        return {
          msg: "Twitter dates are empty"
        }
      }
      var isToDateValid = moment(dates.fromDate) <= moment(new Date());
      if (!dates.fromDate || !dates.toDate || !isToDateValid) {
        return {
          msg: "Twitter dates are not valid"
        }
      }
    }
  },
Example #28
0
 .attr('data-title', function(d) {
   return Utils.formatNumber(d.mapviews) + ' ' + pluralizeString('mapview', d.mapviews) + ( d.today ? (' today') : (' on ' + d.when) )
 })
Example #29
0
  render: function() {
    this.clearSubViews();
    var vis = this.model;
    var table = vis.tableMetadata();
    var tags = vis.get('tags') || [];

    var url = vis.viewUrl(this.user);
    url = (this.router.model.get('liked') && !vis.permission.hasAccess(this.user)) ? url.public() : url.edit();

    var d = {
      isRaster:                vis.get('kind') === 'raster',
      geometryType:            table.statsGeomColumnTypes().length > 0 ? table.statsGeomColumnTypes()[0] : '',
      title:                   vis.get('name'),
      datasetUrl:              encodeURI(url),
      isOwner:                 vis.permission.isOwner(this.user),
      owner:                   vis.permission.owner.renderData(this.user),
      showPermissionIndicator: !vis.permission.hasWriteAccess(this.user),
      privacy:                 vis.get('privacy').toLowerCase(),
      likes:                   vis.get('likes') || 0,
      timeDiff:                moment(vis.get('updated_at')).fromNow(),
      tags:                    tags,
      tagsCount:               tags.length,
      router:                  this.router,
      maxTagsToShow:           3,
      rowCount:                undefined,
      datasetSize:             undefined,
      syncStatus:              undefined,
      syncRanAt:               undefined,
      fromExternalSource:      ""
    };

    var rowCount = table.get('row_count');
    if (rowCount >= 0) {
      d.rowCount = ( rowCount < 10000 ? Utils.formatNumber(rowCount) : Utils.readizableNumber(rowCount) );
      d.pluralizedRows = pluralizeString('Row', rowCount);
    }

    if (!_.isEmpty(vis.get("synchronization"))) {
      d.fromExternalSource = vis.get("synchronization").from_external_source;
    }

    var datasetSize = table.get('size');
    if (datasetSize >= 0) {
      d.datasetSize = Utils.readablizeBytes(datasetSize, true);
    }

    if (!_.isEmpty(vis.get("synchronization"))) {
      d.syncRanAt = moment(vis.get("synchronization").ran_at || new Date()).fromNow();
      d.syncStatus = vis.get("synchronization").state;
    }

    this.$el.html(this.template(d));

    this._renderDescription();
    this._renderTags();
    this._renderLikesIndicator();
    this._renderTooltips();

    // Item selected?
    this.$el[ vis.get('selected') ? 'addClass' : 'removeClass' ]('is--selected');

    return this;
  },
var _parsedDescription = function (description) {
  return description
    ? Utils.stripHTML(markdown.toHTML(description))
    : null;
};