diff --git a/NEWS.md b/NEWS.md index ec509daef5a5..13e810e750c7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,7 @@ ------------------- * Now the owner of the dataset is going to receive an email when the synchronization fails hits the max allowed number [#3501](https://github.com/CartoDB/cartodb/issues/3501) * If the dataset don't have an associated map we avoid to use the zoom property [#5447](https://github.com/CartoDB/cartodb/issues/5447) +* Display custom attribution of layers in the editor and embeds [#5388](https://github.com/CartoDB/cartodb/pull/5388) 3.11.0 (2015-09-09) ------------------- diff --git a/app/controllers/admin/visualizations_controller.rb b/app/controllers/admin/visualizations_controller.rb index 6a28c9c0ec26..5143a842b9f4 100644 --- a/app/controllers/admin/visualizations_controller.rb +++ b/app/controllers/admin/visualizations_controller.rb @@ -226,7 +226,7 @@ def public_map @disqus_shortname = @visualization.user.disqus_shortname.presence || 'cartodb' @visualization_count = @visualization.user.public_visualization_count @related_tables = @visualization.related_tables - @related_visualizations = @visualization.related_visualizations + @related_canonical_visualizations = @visualization.related_canonical_visualizations @related_tables_owners = Hash.new @related_tables.each { |table| unless @related_tables_owners.include?(table.user_id) @@ -273,7 +273,7 @@ def show_organization_public_map @disqus_shortname = @visualization.user.disqus_shortname.presence || 'cartodb' @visualization_count = @visualization.user.public_visualization_count @related_tables = @visualization.related_tables - @related_visualizations = @visualization.related_visualizations + @related_canonical_visualizations = @visualization.related_canonical_visualizations @public_tables_count = @visualization.user.public_table_count @nonpublic_tables_count = @related_tables.select{|p| !p.public? }.count @@ -323,7 +323,7 @@ def show_protected_public_map @disqus_shortname = @visualization.user.disqus_shortname.presence || 'cartodb' @visualization_count = @visualization.user.public_visualization_count @related_tables = @visualization.related_tables - @related_visualizations = @visualization.related_visualizations + @related_canonical_visualizations = @visualization.related_canonical_visualizations @public_tables_count = @visualization.user.public_table_count @nonpublic_tables_count = @related_tables.select{|p| !p.public? }.count diff --git a/app/controllers/api/json/visualizations_controller.rb b/app/controllers/api/json/visualizations_controller.rb index 13831cc9fd26..5a202d856fa0 100644 --- a/app/controllers/api/json/visualizations_controller.rb +++ b/app/controllers/api/json/visualizations_controller.rb @@ -89,7 +89,6 @@ def update # Don't allow to modify next_id/prev_id, force to use set_next_id() vis_data.delete(:prev_id) || vis_data.delete('prev_id') vis_data.delete(:next_id) || vis_data.delete('next_id') - # when a table gets renamed, first it's canonical visualization is renamed, so we must revert renaming if that failed # This is far from perfect, but works without messing with table-vis sync and their two backends if vis.table? diff --git a/app/controllers/carto/admin/visualization_public_map_adapter.rb b/app/controllers/carto/admin/visualization_public_map_adapter.rb index 045ad6a89eae..43ad83d0954d 100644 --- a/app/controllers/carto/admin/visualization_public_map_adapter.rb +++ b/app/controllers/carto/admin/visualization_public_map_adapter.rb @@ -74,14 +74,14 @@ def public_with_link? @visualization.is_link_privacy? end - def related_visualizations - @visualization.related_visualizations.map { |rv| + def related_canonical_visualizations + @visualization.related_canonical_visualizations.map { |rv| Carto::Admin::VisualizationPublicMapAdapter.new(rv, @current_viewer) if rv.is_public? }.compact end def related_visualizations_geometry_types - related_visualizations.collect(&:geometry_types).flatten.uniq + related_canonical_visualizations.collect(&:geometry_types).flatten.uniq end def related_tables_geometry_types diff --git a/app/controllers/carto/api/visualization_vizjson_adapter.rb b/app/controllers/carto/api/visualization_vizjson_adapter.rb index 42199dc995ec..d0bc2386ec38 100644 --- a/app/controllers/carto/api/visualization_vizjson_adapter.rb +++ b/app/controllers/carto/api/visualization_vizjson_adapter.rb @@ -8,7 +8,8 @@ class VisualizationVizJSONAdapter include Carto::HtmlSafe delegate [:id, :map, :qualified_name, :likes, :description, :retrieve_named_map?, :password_protected?, :overlays, - :prev_id, :next_id, :transition_options, :has_password?, :parent_id, :get_auth_tokens, :user, :related_visualizations + :prev_id, :next_id, :transition_options, :has_password?, :parent_id, :get_auth_tokens, :user, + :related_canonical_visualizations ] => :visualization attr_reader :visualization @@ -29,7 +30,7 @@ def layers(kind) end def attributions_from_derived_visualizations - @visualization.related_visualizations.map(&:attributions).reject {|attribution| attribution.blank?} + @visualization.related_canonical_visualizations.map(&:attributions).reject {|attribution| attribution.blank?} end def children diff --git a/app/controllers/carto/api/vizjson_presenter.rb b/app/controllers/carto/api/vizjson_presenter.rb index 74376088d457..bef26f92c58b 100644 --- a/app/controllers/carto/api/vizjson_presenter.rb +++ b/app/controllers/carto/api/vizjson_presenter.rb @@ -20,7 +20,6 @@ def to_vizjson(options={}) private - def calculate_vizjson(options={}) vizjson_options = { full: false, diff --git a/app/helpers/redis_vizjson_cache.rb b/app/helpers/redis_vizjson_cache.rb index b586d7a74ae4..ade533d62988 100644 --- a/app/helpers/redis_vizjson_cache.rb +++ b/app/helpers/redis_vizjson_cache.rb @@ -11,7 +11,6 @@ def initialize(redis_cache=$tables_metadata) @redis = redis_cache end - def cached(visualization_id, https_flag=false) key = key(visualization_id, https_flag) value = redis.get(key) diff --git a/app/models/carto/visualization.rb b/app/models/carto/visualization.rb index b610a40d93ee..c23708a7bcc6 100644 --- a/app/models/carto/visualization.rb +++ b/app/models/carto/visualization.rb @@ -77,8 +77,8 @@ def related_tables @related_tables ||= get_related_tables end - def related_visualizations - @related_visualizations ||= get_related_visualizations + def related_canonical_visualizations + @related_canonical_visualizations ||= get_related_canonical_visualizations end def stats @@ -313,8 +313,12 @@ def get_related_tables map.carto_and_torque_layers.flat_map { |layer| layer.affected_tables}.uniq end - def get_related_visualizations - Carto::Visualization.where(map_id: related_tables.collect(&:map_id), type: TYPE_CANONICAL).all + def get_related_canonical_visualizations + get_related_visualizations_by_types([TYPE_CANONICAL]) + end + + def get_related_visualizations_by_types(types) + Carto::Visualization.where(map_id: related_tables.collect(&:map_id), type: types).all end def has_write_permission?(user) diff --git a/app/models/visualization/member.rb b/app/models/visualization/member.rb index e2eff232d061..cd53ac91d858 100644 --- a/app/models/visualization/member.rb +++ b/app/models/visualization/member.rb @@ -319,10 +319,16 @@ def description_html_safe if description.present? renderer = Redcarpet::Render::Safe markdown = Redcarpet::Markdown.new(renderer, extensions = {}) - markdown.render description + markdown.render description end end + def attributions=(value) + self.dirty = true if value != @attributions + self.attributions_changed = true if value != @attributions + super(value) + end + def permission_id=(permission_id) self.permission_change_valid = false self.permission_change_valid = true if (@permission_id.nil? || @permission_id == permission_id) @@ -439,6 +445,7 @@ def non_dependent? def invalidate_cache invalidate_redis_cache invalidate_varnish_cache + parent.invalidate_cache unless parent_id.nil? end @@ -475,7 +482,7 @@ def password=(value) end def has_password? - ( !@password_salt.nil? && !@encrypted_password.nil? ) + ( !@password_salt.nil? && !@encrypted_password.nil? ) end def is_password_valid?(password) @@ -494,7 +501,7 @@ def make_auth_token 10.times do digest = secure_digest(digest, TOKEN_DIGEST) end - digest + digest end def get_auth_tokens @@ -642,13 +649,13 @@ def license_info end def attributions_from_derived_visualizations - related_visualizations.map(&:attributions).reject {|attribution| attribution.blank?} + related_canonical_visualizations.map(&:attributions).reject {|attribution| attribution.blank?} end private attr_reader :repository, :name_checker, :validator - attr_accessor :privacy_changed, :name_changed, :old_name, :permission_change_valid, :dirty + attr_accessor :privacy_changed, :name_changed, :old_name, :permission_change_valid, :dirty, :attributions_changed def embed_redis_cache @embed_redis_cache ||= EmbedRedisCache.new($tables_metadata) @@ -708,11 +715,7 @@ def do_store(propagate_changes=true, table_privacy_changed=false) raise CartoDB::InvalidMember end - # previously we used 'invalidate_cache' but due to public_map displaying all the user public visualizations, - # now we need to purgue everything to avoid cached stale data or public->priv still showing scenarios - if name_changed || privacy_changed || table_privacy_changed || dirty - invalidate_cache - end + perform_invalidations(table_privacy_changed) set_timestamps @@ -731,10 +734,26 @@ def do_store(propagate_changes=true, table_privacy_changed=false) save_named_map + propagate_attribution_change if table if type == TYPE_REMOTE || type == TYPE_CANONICAL propagate_privacy_and_name_to(table) if table and propagate_changes else - propagate_name_to(table) if !table.nil? and propagate_changes + propagate_name_to(table) if table and propagate_changes + end + end + + def perform_invalidations(table_privacy_changed) + # previously we used 'invalidate_cache' but due to public_map displaying all the user public visualizations, + # now we need to purgue everything to avoid cached stale data or public->priv still showing scenarios + if name_changed || privacy_changed || table_privacy_changed || dirty + invalidate_cache + end + + # When a table's relevant data is changed, propagate to all who use it or relate to it + if dirty && table + table.affected_visualizations.each do |affected_vis| + affected_vis.invalidate_cache + end end end @@ -805,6 +824,20 @@ def propagate_name_to(table) raise CartoDB::InvalidMember.new(exception.to_s) end + def propagate_attribution_change + return unless attributions_changed + + # This includes both the canonical and derived visualizations + table.affected_visualizations.each do |affected_visualization| + affected_visualization.layers(:carto_and_torque).each do |layer| + if layer.options['table_name'] == table.name + layer.options['attribution'] = self.attributions + layer.save + end + end + end + end + def revert_name_change(previous_name) self.name = previous_name store diff --git a/app/models/visualization/relator.rb b/app/models/visualization/relator.rb index af322d557682..30f681600c19 100644 --- a/app/models/visualization/relator.rb +++ b/app/models/visualization/relator.rb @@ -17,9 +17,9 @@ class Relator named_map: :named_maps_layers } - INTERFACE = %w{ overlays map user table related_templates related_tables related_visualizations layers - stats mapviews total_mapviews single_data_layer? synchronization is_synced? permission parent - children support_tables prev_list_item next_list_item likes likes_count reload_likes + INTERFACE = %w{ overlays map user table related_templates related_tables related_canonical_visualizations + layers stats mapviews total_mapviews single_data_layer? synchronization is_synced? permission + parent children support_tables prev_list_item next_list_item likes likes_count reload_likes estimated_row_count actual_row_count } def initialize(attributes={}) @@ -105,8 +105,8 @@ def related_tables .flat_map{|layer| layer.affected_tables.map{|t| t.service}}.uniq end - def related_visualizations - @related_visualizations ||= get_related_visualizations + def related_canonical_visualizations + @related_canonical_visualizations ||= get_related_canonical_visualizations end def layers(kind) @@ -165,10 +165,15 @@ def likes_search Like.where(subject: @id) end - def get_related_visualizations + def get_related_canonical_visualizations + get_related_visualizations_by_types([CartoDB::Visualization::Member::TYPE_CANONICAL]) + end + + def get_related_visualizations_by_types(types) related_map_ids = related_tables.map(&:map_id) - CartoDB::Visualization::Collection.new.fetch(map_id: related_map_ids, type: CartoDB::Visualization::Member::TYPE_CANONICAL) + CartoDB::Visualization::Collection.new.fetch(map_id: related_map_ids, type: types) end + end end end diff --git a/app/views/admin/visualizations/public_map.html.erb b/app/views/admin/visualizations/public_map.html.erb index 156495a8e8d6..30533e637b49 100644 --- a/app/views/admin/visualizations/public_map.html.erb +++ b/app/views/admin/visualizations/public_map.html.erb @@ -171,8 +171,8 @@