diff --git a/app/assets/stylesheets/editor/custom_basemap_dialog.css.scss b/app/assets/stylesheets/editor/custom_basemap_dialog.css.scss index 49675c510d75..ba564e765b29 100644 --- a/app/assets/stylesheets/editor/custom_basemap_dialog.css.scss +++ b/app/assets/stylesheets/editor/custom_basemap_dialog.css.scss @@ -15,4 +15,12 @@ right: 14px; z-index: 2; &:hover { cursor: pointer } -} \ No newline at end of file +} + + +// WMS panel view +.WMSSSelectLayer-Filter { + width: 900px; + margin:auto; + z-index: 0; +} diff --git a/app/controllers/api/json/overlays_controller.rb b/app/controllers/api/json/overlays_controller.rb index 5dbe62b4f237..dade9a5047e1 100644 --- a/app/controllers/api/json/overlays_controller.rb +++ b/app/controllers/api/json/overlays_controller.rb @@ -8,24 +8,9 @@ class Api::Json::OverlaysController < Api::ApplicationController include CartoDB - ssl_required :index, :show, :create, :update, :destroy - before_filter :check_owner_by_vis, only: [ :index, :create ] - before_filter :check_owner_by_id, only: [ :show, :update, :destroy ] - - def index - # TODO: PATCH - vis_id = params.fetch('visualization_id') - vis_id, schema = table_and_schema_from(vis_id) - - vis, = locator.get(vis_id, CartoDB.extract_subdomain(request)) - visualization_id = vis.id - collection = Overlay::Collection.new( - visualization_id: visualization_id, - ).fetch - render_jsonp(collection) - rescue KeyError - head :not_found - end + ssl_required :create, :update, :destroy + before_filter :check_owner_by_vis, only: [ :create ] + before_filter :check_owner_by_id, only: [ :update, :destroy ] def create member_attributes = payload.merge( @@ -39,13 +24,6 @@ def create render_jsonp(member.attributes) end - def show - member = Overlay::Member.new(id: params.fetch('id')).fetch - render_jsonp(member.attributes) - rescue KeyError - head :not_found - end - def update member = Overlay::Member.new(id: params.fetch('id')).fetch member.attributes = payload diff --git a/app/controllers/api/json/visualizations_controller.rb b/app/controllers/api/json/visualizations_controller.rb index 6287abcdff95..f32720bbefd7 100644 --- a/app/controllers/api/json/visualizations_controller.rb +++ b/app/controllers/api/json/visualizations_controller.rb @@ -14,20 +14,13 @@ class Api::Json::VisualizationsController < Api::ApplicationController include CartoDB - ssl_allowed :vizjson2, :notify_watching, :list_watching, :likes_count, :likes_list, :add_like, :is_liked, - :remove_like - ssl_required :index, :show, :create, :update, :destroy, :set_next_id unless Rails.env.development? || Rails.env.test? - skip_before_filter :api_authorization_required, only: [:vizjson2, :likes_count, :likes_list, :add_like, - :is_liked, :remove_like, :index] - before_filter :optional_api_authorization, only: [:likes_count, :likes_list, :add_like, :is_liked, :remove_like, - :index, :vizjson2] - before_filter :table_and_schema_from_params, only: [:show, :update, :destroy, :stats, :vizjson2, - :notify_watching, :list_watching, :likes_count, :likes_list, - :add_like, :is_liked, :remove_like, :set_next_id] - - def index - current_user ? index_logged_in : index_not_logged_in - end + ssl_allowed :notify_watching, :list_watching, :add_like, :remove_like + ssl_required :create, :update, :destroy, :set_next_id unless Rails.env.development? || Rails.env.test? + skip_before_filter :api_authorization_required, only: [:add_like, :remove_like] + before_filter :optional_api_authorization, only: [:add_like, :remove_like] + before_filter :table_and_schema_from_params, only: [:update, :destroy, :stats, + :notify_watching, :list_watching, + :add_like, :remove_like, :set_next_id] def create vis_data = payload @@ -125,15 +118,6 @@ def create render_jsonp({ errors: { named_maps: exception } }, 400) end - def show - vis, = locator.get(@table_id, CartoDB.extract_subdomain(request)) - return(head 404) unless vis - return(head 403) unless vis.has_permission?(current_user, Visualization::Member::PERMISSION_READONLY) - render_jsonp(vis) - rescue KeyError - head(404) - end - def update vis, = locator.get(@table_id, CartoDB.extract_subdomain(request)) return(head 404) unless vis @@ -200,28 +184,6 @@ def destroy render_jsonp({ errors: { named_maps: exception } }, 400) end - def vizjson2 - visualization, = locator.get(@table_id, CartoDB.extract_subdomain(request)) - return(head 404) unless visualization - return(head 403) unless allow_vizjson_v2_for?(visualization) - set_vizjson_response_headers_for(visualization) - render_jsonp(visualization.to_vizjson({https_request: request.protocol == 'https://'})) - rescue KeyError => exception - render(text: exception.message, status: 403) - rescue CartoDB::NamedMapsWrapper::HTTPResponseError => exception - CartoDB.notify_exception(exception, { user: current_user, template_data: exception.template_data }) - render_jsonp({ errors: { named_maps_api: "Communication error with tiler API. HTTP Code: #{exception.message}" } }, 400) - rescue CartoDB::NamedMapsWrapper::NamedMapDataError => exception - CartoDB.notify_exception(exception) - render_jsonp({ errors: { named_map: exception.message } }, 400) - rescue CartoDB::NamedMapsWrapper::NamedMapsDataError => exception - CartoDB.notify_exception(exception) - render_jsonp({ errors: { named_maps: exception.message } }, 400) - rescue => exception - CartoDB.notify_exception(exception) - raise exception - end - def notify_watching vis = Visualization::Member.new(id: @table_id).fetch return(head 403) unless vis.has_permission?(current_user, Visualization::Member::PERMISSION_READONLY) @@ -270,36 +232,6 @@ def set_next_id rescue render_jsonp({ errors: ['Unknown error'] }, 400) end - - # Does not mandate a current_viewer except if vis is not public - def likes_count - vis = Visualization::Member.new(id: @table_id).fetch - if vis.privacy != Visualization::Member::PRIVACY_PUBLIC && vis.privacy != Visualization::Member::PRIVACY_LINK - raise KeyError if current_viewer.nil? || !vis.has_permission?(current_viewer, Visualization::Member::PERMISSION_READONLY) - end - - render_jsonp({ - id: vis.id, - likes: vis.likes.count - }) - rescue KeyError => exception - render(text: exception.message, status: 403) - end - - # Does not mandate a current_viewer except if vis is not public - def likes_list - vis = Visualization::Member.new(id: @table_id).fetch - if vis.privacy != Visualization::Member::PRIVACY_PUBLIC && vis.privacy != Visualization::Member::PRIVACY_LINK - raise KeyError if current_viewer.nil? || !vis.has_permission?(current_viewer, Visualization::Member::PERMISSION_READONLY) - end - - render_jsonp({ - id: vis.id, - likes: vis.likes.map { |like| {actor_id: like.actor } } - }) - rescue KeyError => exception - render(text: exception.message, status: 403) - end def add_like return(head 403) unless current_viewer @@ -322,31 +254,6 @@ def add_like render(text: "You've already liked this visualization", status: 400) end - def is_liked - if current_viewer - vis = Visualization::Member.new(id: @table_id).fetch - raise KeyError if vis.privacy != Visualization::Member::PRIVACY_PUBLIC && - vis.privacy != Visualization::Member::PRIVACY_LINK && - !vis.has_permission?(current_viewer, Visualization::Member::PERMISSION_READONLY) - render_jsonp({ - id: vis.id, - likes: vis.likes.count, - liked: vis.liked_by?(current_viewer.id) - }) - else - vis = Visualization::Member.new(id: @table_id).fetch - raise KeyError if vis.privacy != Visualization::Member::PRIVACY_PUBLIC && - vis.privacy != Visualization::Member::PRIVACY_LINK - render_jsonp({ - id: vis.id, - likes: vis.likes.count, - liked: false - }) - end - rescue KeyError => exception - render(text: exception.message, status: 403) - end - def remove_like return(head 403) unless current_viewer @@ -452,92 +359,6 @@ def prepare_params_for_total_count(params) end end - def index_not_logged_in - public_visualizations = [] - total_liked_entries = 0 - total_shared_entries = 0 - total_user_entries = 0 - user = User.where(username: CartoDB.extract_subdomain(request)).first - - unless user.nil? - filtered_params = params.dup.merge(scope_for(user)) - filtered_params[:unauthenticated] = true - - params_for_total_count = prepare_params_for_total_count(filtered_params) - total_user_entries = Visualization::Collection.new.count_total(params_for_total_count) - - collection = Visualization::Collection.new.fetch(filtered_params) - public_visualizations = collection.map { |vis| - begin - vis.to_hash( - public_fields_only: true, - related: false, - table: vis.table - ) - rescue => exception - puts exception.to_s + exception.backtrace.join("\n") - end - }.compact - - total_liked_entries = collection.total_liked_entries(params_for_total_count[:type]) - total_shared_entries = collection.total_shared_entries(params_for_total_count[:type]) - end - - response = { - visualizations: public_visualizations, - total_entries: public_visualizations.length, - total_user_entries: total_user_entries, - total_likes: total_liked_entries, - total_shared: total_shared_entries - } - render_jsonp(response) - end - - def index_logged_in - users_cache = {} - filters = params.dup.merge(scope_for(current_user)) - - collection = Visualization::Collection.new.fetch(filters) - - params_for_total_count = prepare_params_for_total_count(filters) - total_user_entries = Visualization::Collection.new.count_total(params_for_total_count) - - table_data = collection.map { |vis| - if vis.table.nil? - nil - else - users_cache[vis.user_id] ||= vis.user - { - name: vis.table.name, - schema: users_cache[vis.user_id].database_schema - } - end - }.compact - synchronizations = synchronizations_by_table_name(table_data) - representation = collection.map { |vis| - begin - vis.to_hash( - related: false, - table_data: !(params[:table_data] =~ /false/), - user: current_user, - table: vis.table, - synchronization: synchronizations[vis.name] - ) - rescue => exception - puts exception.to_s + exception.backtrace.join("\n") - end - }.compact - - response = { - visualizations: representation, - total_entries: collection.total_entries, - total_user_entries: total_user_entries, - total_likes: collection.total_liked_entries(params_for_total_count[:type]), - total_shared: collection.total_shared_entries(params_for_total_count[:type]) - } - render_jsonp(response) - end - # Need to always send request object to visualizations upon rendering their json def render_jsonp(obj, status = 200, options = {}) super(obj, status, options.merge({request: request})) diff --git a/app/controllers/carto/api/visualizations_controller.rb b/app/controllers/carto/api/visualizations_controller.rb index 1e88802b1618..e16732933a6e 100644 --- a/app/controllers/carto/api/visualizations_controller.rb +++ b/app/controllers/carto/api/visualizations_controller.rb @@ -2,12 +2,14 @@ require_relative 'vizjson_presenter' require_relative '../../../models/visualization/stats' require_relative 'paged_searcher' +require_dependency 'carto/uuidhelper' module Carto module Api class VisualizationsController < ::Api::ApplicationController include VisualizationSearcher include PagedSearcher + include Carto::UUIDHelper ssl_required :index, :show ssl_allowed :vizjson2, :likes_count, :likes_list, :is_liked, :list_watching @@ -17,7 +19,7 @@ class VisualizationsController < ::Api::ApplicationController before_filter :optional_api_authorization, only: [:index, :vizjson2, :is_liked] before_filter :id_and_schema_from_params - before_filter :load_table, only: [:vizjson2] + before_filter :load_by_name_or_id, only: [:vizjson2] before_filter :load_visualization, only: [:likes_count, :likes_list, :is_liked, :show, :stats, :list_watching] def show @@ -65,7 +67,7 @@ def is_liked render_jsonp({ id: @visualization.id, likes: @visualization.likes.count, - liked: @visualization.is_liked_by_user_id?(current_viewer.id) + liked: current_viewer ? @visualization.is_liked_by_user_id?(current_viewer.id) : false }) end @@ -96,20 +98,15 @@ def list_watching private - def load_table - # TODO: refactor this for vizjson, that uses to look for a visualization, so it should come first + def load_by_name_or_id + @table = is_uuid?(@id) ? Carto::UserTable.where(id: @id).first : nil - @table = Carto::UserTable.where(id: @id).first - # TODO: id should _really_ contain either an id of a user_table or a visualization?? - # Some tests fail if not, and older controller works that way, but... + # INFO: id should _really_ contain either an id of a user_table or a visualization, but for legacy reasons... if @table @visualization = @table.visualization else - @table = Visualization.where(id: @id).first - @visualization = @table - # TODO: refactor load_table duplication - return render(text: 'Visualization does not exist', status: 404) if @visualization.nil? - return render(text: 'Visualization not viewable', status: 403) if !@visualization.is_viewable_by_user?(current_viewer) + load_visualization + @table = @visualization end end diff --git a/config/routes.rb b/config/routes.rb index 60378b31d645..8d72a5d19e45 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -270,17 +270,16 @@ end - # Remember to add routes to /lib/assets/javascript/cartodb/app.js -> applyPatchNewVisualizationUrl() scope :module => 'carto/api', :format => :json do - # Visualizations - get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/viz' => 'visualizations#index', as: :api_v1_1_visualizations_index - get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/viz/:id' => 'visualizations#show', as: :api_v1_1_visualizations_show, constraints: { id: /[^\/]+/ } - get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/viz/:id/likes' => 'visualizations#likes_count', as: :api_v1_1_visualizations_likes_count, constraints: { id: /[^\/]+/ } - get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/viz/:id/likes/detailed' => 'visualizations#likes_list', as: :api_v1_1_visualizations_likes_list, constraints: { id: /[^\/]+/ } - get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/viz/:id/like' => 'visualizations#is_liked', as: :api_v1_1_visualizations_is_liked, constraints: { id: /[^\/]+/ } + # V1 api/json calls - get '(/user/:user_domain)(/u/:user_domain)/api/v2_1/viz/:id/viz' => 'visualizations#vizjson2', as: :api_v2_1_visualizations_vizjson, constraints: { id: /[^\/]+/ } + # Visualizations + get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz' => 'visualizations#index', as: :api_v1_visualizations_index + get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id' => 'visualizations#show', as: :api_v1_visualizations_show, constraints: { id: /[^\/]+/ } + get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/likes' => 'visualizations#likes_count', as: :api_v1_visualizations_likes_count, constraints: { id: /[^\/]+/ } + get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/likes/detailed' => 'visualizations#likes_list', as: :api_v1_visualizations_likes_list, constraints: { id: /[^\/]+/ } + get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/like' => 'visualizations#is_liked', as: :api_v1_visualizations_is_liked, constraints: { id: /[^\/]+/ } # Tables get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/tables/:id' => 'tables#show', as: :api_v1_1_tables_show, constraints: { id: /[^\/]+/ } @@ -317,8 +316,8 @@ get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/maps/:id' => 'maps#show', as: :api_v1_1_maps_show # Overlays - get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/viz/:visualization_id/overlays' => 'overlays#index', as: :api_v1_1_visualizations_overlays_index, constraints: { visualization_id: /[^\/]+/ } - get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/viz/:visualization_id/overlays/:id' => 'overlays#show', as: :api_v1_1_visualizations_overlays_show, constraints: { visualization_id: /[^\/]+/ } + get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:visualization_id/overlays' => 'overlays#index', as: :api_v1_visualizations_overlays_index, constraints: { visualization_id: /[^\/]+/ } + get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:visualization_id/overlays/:id' => 'overlays#show', as: :api_v1_visualizations_overlays_show, constraints: { visualization_id: /[^\/]+/ } # Synchronizations # TODO: deprecated? @@ -328,7 +327,7 @@ get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/synchronizations/:id/sync_now' => 'synchronizations#syncing?', as: :api_v1_1_synchronizations_syncing # Watching - get '(/user/:user_domain)(/u/:user_domain)/api/v1_1/viz/:id/watching' => 'visualizations#list_watching', as: :api_v1_1_visualizations_notify_watching, constraints: { id: /[^\/]+/ } + get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/watching' => 'visualizations#list_watching', as: :api_v1_visualizations_notify_watching, constraints: { id: /[^\/]+/ } # Oembed get '(/user/:user_domain)(/u/:user_domain)/api/v1/oembed' => 'oembed#show', as: :api_v1_oembed @@ -351,6 +350,13 @@ # User creations get '(/user/:user_domain)(/u/:user_domain)/api/v1/user_creations/:id' => 'user_creations#show', as: :api_v1_user_creations_show, constraints: { id: /[^\/]+/ } + + # V2 api/json calls + + # Visualizations + + get '(/user/:user_domain)(/u/:user_domain)/api/v2/viz/:id/viz' => 'visualizations#vizjson2', as: :api_v2_visualizations_vizjson, constraints: { id: /[^\/]+/ } + end scope :module => 'api/json', :format => :json do @@ -426,24 +432,16 @@ put '(/user/:user_domain)(/u/:user_domain)/api/v1/geocodings/:id' => 'geocodings#update', as: :api_v1_geocodings_update # Visualizations - get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz' => 'visualizations#index', as: :api_v1_visualizations_index post '(/user/:user_domain)(/u/:user_domain)/api/v1/viz' => 'visualizations#create', as: :api_v1_visualizations_create - get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id' => 'visualizations#show', as: :api_v1_visualizations_show, constraints: { id: /[^\/]+/ } put '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id' => 'visualizations#update', as: :api_v1_visualizations_update, constraints: { id: /[^\/]+/ } delete '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id' => 'visualizations#destroy', as: :api_v1_visualizations_destroy, constraints: { id: /[^\/]+/ } - get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:visualization_id/overlays' => 'overlays#index', as: :api_v1_visualizations_overlays_index, constraints: { visualization_id: /[^\/]+/ } post '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:visualization_id/overlays' => 'overlays#create', as: :api_v1_visualizations_overlays_create, constraints: { visualization_id: /[^\/]+/ } - get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:visualization_id/overlays/:id' => 'overlays#show', as: :api_v1_visualizations_overlays_show, constraints: { visualization_id: /[^\/]+/ } put '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:visualization_id/overlays/:id' => 'overlays#update', as: :api_v1_visualizations_overlays_update, constraints: { visualization_id: /[^\/]+/ } delete '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:visualization_id/overlays/:id' => 'overlays#destroy', as: :api_v1_visualizations_overlays_destroy, constraints: { visualization_id: /[^\/]+/ } # TODO: deprecate? - get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/watching' => 'visualizations#list_watching', as: :api_v1_visualizations_notify_watching, constraints: { id: /[^\/]+/ } put '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/watching' => 'visualizations#notify_watching', as: :api_v1_visualizations_list_watching, constraints: { id: /[^\/]+/ } put '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/next_id' => 'visualizations#set_next_id', as: :api_v1_visualizations_set_next_id, constraints: { id: /[^\/]+/ } - get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/likes' => 'visualizations#likes_count', as: :api_v1_visualizations_likes_count, constraints: { id: /[^\/]+/ } - get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/likes/detailed' => 'visualizations#likes_list', as: :api_v1_visualizations_likes_list, constraints: { id: /[^\/]+/ } post '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/like' => 'visualizations#add_like', as: :api_v1_visualizations_add_like, constraints: { id: /[^\/]+/ } - get '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/like' => 'visualizations#is_liked', as: :api_v1_visualizations_is_liked, constraints: { id: /[^\/]+/ } delete '(/user/:user_domain)(/u/:user_domain)/api/v1/viz/:id/like' => 'visualizations#remove_like', as: :api_v1_visualizations_remove_like, constraints: { id: /[^\/]+/ } # Tags @@ -471,9 +469,6 @@ # V2 # -- - # Visualizations - get '(/user/:user_domain)(/u/:user_domain)/api/v2/viz/:id/viz' => 'visualizations#vizjson2', as: :api_v2_visualizations_vizjson, constraints: { id: /[^\/]+/ } - # WMS get '(/user/:user_domain)(/u/:user_domain)/api/v2/wms' => 'wms#proxy', as: :api_v2_wms_proxy diff --git a/lib/assets/javascripts/cartodb/app.js b/lib/assets/javascripts/cartodb/app.js index ac9989d5132a..0873cdf855fb 100644 --- a/lib/assets/javascripts/cartodb/app.js +++ b/lib/assets/javascripts/cartodb/app.js @@ -221,46 +221,38 @@ Backbone.saveAbort = function() { }; // TODO: this routing code should be removed -function applyPatchNewVisualizationUrl() { - - // collections only needs read method - cdb.config.setUrlVersion('visualizations', 'read', 'v1_1'); - - // models can have: read, update, delete and create - cdb.config.setUrlVersion('visualization', 'read', 'v1_1'); - //cdb.config.setUrlVersion('visualization', 'update', 'v1_1'); - cdb.config.setUrlVersion('like', 'read', 'v1_1'); - cdb.config.setUrlVersion('vizjson', 'read', 'v2_1'); - cdb.config.setUrlVersion('overlays', 'read', 'v1_1'); - - cdb.config.setUrlVersion('watching', 'read', 'v1_1'); -} - function applyPatchNewTableUrls() { cdb.config.setUrlVersion('table', 'read', 'v1_1'); cdb.config.setUrlVersion('record', 'read', 'v1_1'); cdb.config.setUrlVersion('column', 'read', 'v1_1'); } +// TODO: this routing code should be removed function applyPatchNewSynchronizationUrls() { cdb.config.setUrlVersion('synchronization', 'read', 'v1_1'); } +// TODO: this routing code should be removed function applyPatchNewImportUrl() { cdb.config.setUrlVersion('import', 'read', 'v1_1'); } +// TODO: this routing code should be removed function applyPatchNewImportsServiceUrl() { cdb.config.setUrlVersion('imports_service', 'read', 'v1_1'); } +// TODO: this routing code should be removed function applyPatchNewGeocodingUrls() { cdb.config.setUrlVersion('geocoding', 'read', 'v1_1'); } +// TODO: this routing code should be removed function applyPatchNewLayerUrls() { cdb.config.setUrlVersion('layer', 'read', 'v1_1'); } + +// TODO: this routing code should be removed function applyPatchNewAssetUrl() { cdb.config.setUrlVersion('asset', 'read', 'v1_1'); } \ No newline at end of file diff --git a/lib/assets/javascripts/cartodb/common/dialogs/add_custom_basemap/wms/select_layer.jst.ejs b/lib/assets/javascripts/cartodb/common/dialogs/add_custom_basemap/wms/select_layer.jst.ejs index 3ac0ea051f3c..cae6f95fd72e 100644 --- a/lib/assets/javascripts/cartodb/common/dialogs/add_custom_basemap/wms/select_layer.jst.ejs +++ b/lib/assets/javascripts/cartodb/common/dialogs/add_custom_basemap/wms/select_layer.jst.ejs @@ -1,15 +1,42 @@
- +
+ + + + <% if (searchQuery && layersFound.length == 0) { %> +
+
+ +
+

Oh! No results

+

+ Unfortunately we couldn't found any layer that matched your search term +

+
+<% } %>