diff --git a/Gemfile b/Gemfile index a04353b2..0d25cb89 100644 --- a/Gemfile +++ b/Gemfile @@ -69,6 +69,7 @@ gem 'terminal-table' gem 'validates_hostname' gem 'webpacker' gem 'yaml_db', git: 'https://0xacab.org/sutty/yaml_db.git' +gem 'kaminari' # database gem 'hairtrigger' diff --git a/Gemfile.lock b/Gemfile.lock index c1f6925c..f516af42 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -320,6 +320,18 @@ GEM jekyll-write-and-commit-changes (0.1.2) jekyll (~> 4) rugged (~> 1) + kaminari (1.2.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.2.1) + kaminari-activerecord (= 1.2.1) + kaminari-core (= 1.2.1) + kaminari-actionview (1.2.1) + actionview + kaminari-core (= 1.2.1) + kaminari-activerecord (1.2.1) + activerecord + kaminari-core (= 1.2.1) + kaminari-core (1.2.1) kramdown (2.3.1) rexml kramdown-parser-gfm (1.1.0) @@ -681,6 +693,7 @@ DEPENDENCIES jekyll-data! jekyll-images jekyll-include-cache + kaminari letter_opener listen (>= 3.0.5, < 3.2) loaf diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 3ef26720..05ae2736 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -24,7 +24,7 @@ class PostsController < ApplicationController # más simple saber si hubo cambios. if stale?([current_usuarie, site, filter_params]) # Todos los artículos de este sitio para el idioma actual - @posts = site.indexed_posts.where(locale: locale) + @posts = site.indexed_posts.where(locale: locale).page(filter_params.delete(:page)) # De este tipo @posts = @posts.where(layout: filter_params[:layout]) if filter_params[:layout] # Que estén dentro de la categoría @@ -154,7 +154,7 @@ class PostsController < ApplicationController # # @return [Hash] def filter_params - @filter_params ||= params.permit(:q, :category, :layout).to_h.select { |_, v| v.present? } + @filter_params ||= params.permit(:q, :category, :layout, :page).to_h.select { |_, v| v.present? } end def site diff --git a/app/models/site.rb b/app/models/site.rb index 58f20745..ddfe2bc9 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -65,9 +65,6 @@ class Site < ApplicationRecord accepts_nested_attributes_for :deploys, allow_destroy: true - # El sitio en Jekyll - attr_reader :jekyll - # XXX: Es importante incluir luego de los callbacks de :load_jekyll include Site::Index @@ -180,29 +177,28 @@ class Site < ApplicationRecord # Trae los datos del directorio _data dentro del sitio def data - unless @jekyll.data.present? - @jekyll.reader.read_data - - # Define los valores por defecto según la llave buscada - @jekyll.data.default_proc = proc do |data, key| - data[key] = case key - when 'layout' then {} - end + unless jekyll.data.present? + run_in_path do + jekyll.reader.read_data + jekyll.data['layouts'] ||= {} end end - @jekyll.data + jekyll.data end # Traer las colecciones. Todos los artículos van a estar dentro de # colecciones. def collections unless @read - @jekyll.reader.read_collections + run_in_path do + jekyll.reader.read_collections + end + @read = true end - @jekyll.collections + jekyll.collections end # Traer la configuración de forma modificable @@ -290,7 +286,9 @@ class Site < ApplicationRecord # # @return [Hash] def theme_layouts - @jekyll.reader.read_layouts + run_in_path do + jekyll.reader.read_layouts + end end # Trae todos los valores disponibles para un campo @@ -332,6 +330,12 @@ class Site < ApplicationRecord status == 'building' end + def jekyll + run_in_path do + @jekyll ||= Jekyll::Site.new(configuration) + end + end + # Cargar el sitio Jekyll # # TODO: En lugar de leer todo junto de una vez, extraer la carga de @@ -345,10 +349,7 @@ class Site < ApplicationRecord def reload_jekyll! reset - - Dir.chdir(path) do - @jekyll = Jekyll::Site.new(configuration) - end + jekyll end def reload @@ -526,4 +527,8 @@ class Site < ApplicationRecord errors.add(:design_id, I18n.t('activerecord.errors.models.site.attributes.design_id.layout_incompatible.error')) end + + def run_in_path(&block) + Dir.chdir path, &block + end end diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index 8b776590..90e30966 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -40,7 +40,7 @@ %section.col = render 'layouts/flash' .d-flex.justify-content-between.align-items-center.pl-2-plus.pr-2-plus.mb-2 - %form + %form{ action: site_posts_path } - @filter_params.each do |param, value| - next if param == 'q' %input{ type: 'hidden', name: param, value: value } @@ -72,14 +72,20 @@ %thead %tr %th.border-0.background-white.position-sticky{ style: 'top: 0; z-index: 2', colspan: '4' } - = submit_tag t('posts.reorder.submit'), class: 'btn' - %button.btn{ data: { action: 'reorder#unselect' } } - = t('posts.reorder.unselect') - %span.badge{ data: { target: 'reorder.counter' } } 0 - %button.btn{ data: { action: 'reorder#up' } }= t('posts.reorder.up') - %button.btn{ data: { action: 'reorder#down' } }= t('posts.reorder.down') - %button.btn{ data: { action: 'reorder#top' } }= t('posts.reorder.top') - %button.btn{ data: { action: 'reorder#bottom' } }= t('posts.reorder.bottom') + .d-flex.flex-row.justify-content-between + %div + = submit_tag t('posts.reorder.submit'), class: 'btn' + %button.btn{ data: { action: 'reorder#unselect' } } + = t('posts.reorder.unselect') + %span.badge{ data: { target: 'reorder.counter' } } 0 + %button.btn{ data: { action: 'reorder#up' } }= t('posts.reorder.up') + %button.btn{ data: { action: 'reorder#down' } }= t('posts.reorder.down') + %button.btn{ data: { action: 'reorder#top' } }= t('posts.reorder.top') + %button.btn{ data: { action: 'reorder#bottom' } }= t('posts.reorder.bottom') + + %div + = link_to_prev_page @posts, t('posts.prev'), class: 'btn' + = link_to_next_page @posts, t('posts.next'), class: 'btn' %tbody - dir = t("locales.#{@locale}.dir") - size = @posts.size @@ -104,19 +110,19 @@ %span{ lang: post.locale, dir: dir }= post.title - if post.front_matter['draft'].present? %span.badge.badge-primary= I18n.t('posts.attributes.draft.label') - - if post.front_matter['categories'].present? - %br - %small - - post.front_matter['categories'].each do |category| - = link_to site_posts_path(@site, **@filter_params.merge(category: category)) do - %span{ lang: post.locale, dir: dir }= category - = '/' unless post.front_matter['categories'].last == category + %br + %small + = link_to @site.layouts[post.layout].humanized_name, site_posts_path(@site, **@filter_params.merge(layout: post.layout)) + - post.front_matter['categories']&.each do |category| + = link_to site_posts_path(@site, **@filter_params.merge(category: category)) do + %span{ lang: post.locale, dir: dir }= category + = '/' unless post.front_matter['categories'].last == category - %td + %td.text-nowrap = post.created_at.strftime('%F') %br/ = post.order - %td + %td.text-nowrap - if @usuarie || policy(post).edit? = link_to t('posts.edit'), edit_site_post_path(@site, post.path), class: 'btn btn-block' - if @usuarie || policy(post).destroy? diff --git a/config/locales/en.yml b/config/locales/en.yml index 01f08b88..f8cc9a4f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -405,6 +405,8 @@ en: en: 'English' ar: 'Arabic' posts: + prev: Previous page + next: Next page empty: "There are no results for those search parameters." caption: Post list attribute_ro: diff --git a/config/locales/es.yml b/config/locales/es.yml index 931f25ed..339e4c03 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -413,6 +413,8 @@ es: en: 'inglés' ar: 'árabe' posts: + prev: Página anterior + next: Página siguiente empty: No hay artículos con estos parámetros de búsqueda. caption: Lista de artículos attribute_ro: diff --git a/config/routes.rb b/config/routes.rb index 1b0f9e0b..12c11630 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -60,6 +60,7 @@ Rails.application.routes.draw do scope '(:locale)' do post :'posts/reorder', to: 'posts#reorder' resources :posts do + get 'p/:page', action: :index, on: :collection get :preview, to: 'posts#preview' end end