diff --git a/app/controllers/changesets_controller.rb b/app/controllers/changesets_controller.rb index 928f1c1ecf..d6dec70adb 100644 --- a/app/controllers/changesets_controller.rb +++ b/app/controllers/changesets_controller.rb @@ -79,28 +79,33 @@ def show @changeset = Changeset.find(params[:id]) case turbo_frame_request_id when "changeset_nodes" - @node_pages, @nodes = paginate(:old_nodes, :conditions => { :changeset_id => @changeset.id }, :order => [:node_id, :version], :per_page => 20, :parameter => "node_page") - render :partial => "elements", :locals => { :type => "node", :elements => @nodes, :pages => @node_pages } + load_nodes + + render :partial => "elements", :locals => { :type => "node", :paginator => @nodes_paginator } when "changeset_ways" - @way_pages, @ways = paginate(:old_ways, :conditions => { :changeset_id => @changeset.id }, :order => [:way_id, :version], :per_page => 20, :parameter => "way_page") - render :partial => "elements", :locals => { :type => "way", :elements => @ways, :pages => @way_pages } + load_ways + + render :partial => "elements", :locals => { :type => "way", :paginator => @ways_paginator } when "changeset_relations" - @relation_pages, @relations = paginate(:old_relations, :conditions => { :changeset_id => @changeset.id }, :order => [:relation_id, :version], :per_page => 20, :parameter => "relation_page") - render :partial => "elements", :locals => { :type => "relation", :elements => @relations, :pages => @relation_pages } + load_relations + + render :partial => "elements", :locals => { :type => "relation", :paginator => @relations_paginator } else @comments = if current_user&.moderator? @changeset.comments.unscope(:where => :visible).includes(:author) else @changeset.comments.includes(:author) end - @node_pages, @nodes = paginate(:old_nodes, :conditions => { :changeset_id => @changeset.id }, :order => [:node_id, :version], :per_page => 20, :parameter => "node_page") - @way_pages, @ways = paginate(:old_ways, :conditions => { :changeset_id => @changeset.id }, :order => [:way_id, :version], :per_page => 20, :parameter => "way_page") - @relation_pages, @relations = paginate(:old_relations, :conditions => { :changeset_id => @changeset.id }, :order => [:relation_id, :version], :per_page => 20, :parameter => "relation_page") + load_nodes + load_ways + load_relations + if @changeset.user.active? && @changeset.user.data_public? changesets = conditions_nonempty(@changeset.user.changesets) @next_by_user = changesets.where("id > ?", @changeset.id).reorder(:id => :asc).first @prev_by_user = changesets.where(:id => ...@changeset.id).reorder(:id => :desc).first end + render :layout => map_layout end rescue ActiveRecord::RecordNotFound @@ -163,4 +168,50 @@ def conditions_bbox(changesets, bbox) def conditions_nonempty(changesets) changesets.where("num_changes > 0") end + + def load_nodes + nodes = OldNode.where(:changeset => @changeset).order(:node_id, :version) + @nodes_paginator = ElementsPaginator.new(nodes, 20, params[:node_page]) + end + + def load_ways + ways = OldWay.where(:changeset => @changeset).order(:way_id, :version) + @ways_paginator = ElementsPaginator.new(ways, 20, params[:way_page]) + end + + def load_relations + relations = OldRelation.where(:changeset => @changeset).order(:relation_id, :version) + @relations_paginator = ElementsPaginator.new(relations, 20, params[:relation_page]) + end + + class ElementsPaginator + attr_reader :elements_count, :elements_per_page, :current_page, :current_page_elements + + def initialize(elements, elements_per_page, current_page = 1) + @elements_count = elements.count + @elements_per_page = elements_per_page.to_i + @current_page = current_page.to_i.clamp(1, pages_count) + @current_page_elements = elements.offset(@elements_per_page * (@current_page - 1)).limit(@elements_per_page) + end + + def pages_count + [1, 1 + ((elements_count - 1) / elements_per_page)].max + end + + def pages + 1..pages_count + end + + def pages_window(window_size, page = current_page) + [page - window_size, pages.first].max..[page + window_size, pages.last].min + end + + def lower_element_number(page = current_page) + (elements_per_page * (page - 1)) + 1 + end + + def upper_element_number(page = current_page) + [elements_per_page * page, elements_count].min + end + end end diff --git a/app/helpers/browse_helper.rb b/app/helpers/browse_helper.rb index 69a8f8fa2e..26ef808219 100644 --- a/app/helpers/browse_helper.rb +++ b/app/helpers/browse_helper.rb @@ -70,33 +70,56 @@ def link_follow(object) "nofollow" if object.tags.empty? end - def type_and_paginated_count(type, pages, selected_page = pages.current_page) - if pages.page_count == 1 + def type_and_paginated_count(type, paginator, page = paginator.current_page) + if paginator.pages_count <= 1 t ".#{type.pluralize}", - :count => pages.item_count + :count => paginator.elements_count else t ".#{type.pluralize}_paginated", - :x => selected_page.first_item, - :y => selected_page.last_item, - :count => pages.item_count + :x => paginator.lower_element_number(page), + :y => paginator.upper_element_number(page), + :count => paginator.elements_count end end - def sidebar_classic_pagination(pages, page_param) + def sidebar_classic_pagination(paginator, page_param) + window_size = 2 max_width_for_default_padding = 35 + pages = paginator.pages + window = paginator.pages_window(window_size) + page_items = [] + + if window.first != pages.first + page_items.push [pages.first.to_s, pages.first] + page_items.push ["...", "disabled"] if window.first - pages.first > 1 + end + + window.each do |page| + if paginator.current_page == page + page_items.push [page.to_s, "active"] + else + page_items.push [page.to_s, page] + end + end + + if window.last != pages.last + page_items.push ["...", "disabled"] if pages.last - window.last > 1 + page_items.push [pages.last.to_s, pages.last] + end + width = 0 - pagination_items(pages, {}).each do |(body)| + page_items.each do |(body)| width += 2 # padding width width += body.length end link_classes = ["page-link", { "px-1" => width > max_width_for_default_padding }] tag.ul :class => "pagination pagination-sm mb-2" do - pagination_items(pages, {}).each do |body, page_or_class| + page_items.each do |body, page_or_class| linked = !(page_or_class.is_a? String) link = if linked - link_to body, url_for(page_param => page_or_class.number), :class => link_classes, **yield(page_or_class) + link_to body, url_for(page_param => page_or_class), :class => link_classes, **yield(page_or_class) else tag.span body, :class => link_classes end diff --git a/app/views/changesets/_elements.html.erb b/app/views/changesets/_elements.html.erb index fd5dd8a26a..838cb71641 100644 --- a/app/views/changesets/_elements.html.erb +++ b/app/views/changesets/_elements.html.erb @@ -1,7 +1,7 @@ <%= turbo_frame_tag "changeset_#{type.pluralize}" do %> - <%= render :partial => "paging_nav", :locals => { :type => type, :pages => pages } %> + <%= render :partial => "paging_nav", :locals => { :type => type, :paginator => paginator } %>