mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-16 15:41:42 +00:00
implementar el buscador en el panel
ahora el índice de artículos incorporar buscador de texto libre. además todos los filtros de búsqueda se mantienen entre búsquedas, entonces al filtrar por tipo de artículo y término, se aplican ambos y al cambiar el tipo se mantiene la búsqueda de texto.
This commit is contained in:
parent
34a05e860d
commit
ad871baca6
8 changed files with 82 additions and 68 deletions
|
@ -21,6 +21,10 @@ $form-feedback-invalid-color: $magenta;
|
||||||
$form-feedback-icon-valid-color: $black;
|
$form-feedback-icon-valid-color: $black;
|
||||||
$component-active-bg: $magenta;
|
$component-active-bg: $magenta;
|
||||||
|
|
||||||
|
$spacers: (
|
||||||
|
2-plus: 0.75rem
|
||||||
|
);
|
||||||
|
|
||||||
@import "bootstrap";
|
@import "bootstrap";
|
||||||
@import "editor";
|
@import "editor";
|
||||||
|
|
||||||
|
|
|
@ -16,29 +16,25 @@ class PostsController < ApplicationController
|
||||||
authorize Post
|
authorize Post
|
||||||
|
|
||||||
@site = find_site
|
@site = find_site
|
||||||
@category = params.dig(:category)
|
@q = params[:q]
|
||||||
@layout = params.dig(:layout)
|
dictionary = IndexedPost.to_dictionary(locale: locale)
|
||||||
@locale = locale
|
|
||||||
|
|
||||||
# XXX: Cada vez que cambiamos un Post tocamos el sitio con lo que es
|
# XXX: Cada vez que cambiamos un Post tocamos el sitio con lo que es
|
||||||
# más simple saber si hubo cambios.
|
# más simple saber si hubo cambios.
|
||||||
if @category || @layout || stale?(@site)
|
if filter_params.present? || stale?(@site)
|
||||||
@posts = @site.posts(lang: locale)
|
# Todos los artículos de este sitio para el idioma actual
|
||||||
@posts = @posts.where(categories: @category) if @category
|
@posts = @site.indexed_posts.where(locale: dictionary)
|
||||||
@posts = @posts.where(layout: @layout) if @layout
|
# De este tipo
|
||||||
|
@posts = @posts.where(layout: filter_params[:layout]) if filter_params[:layout]
|
||||||
|
# Que estén dentro de la categoría
|
||||||
|
@posts = @posts.in_category(filter_params[:category]) if filter_params[:category]
|
||||||
|
# Aplicar los parámetros de búsqueda
|
||||||
|
@posts = @posts.search(locale, filter_params[:q]) if filter_params[:q].present?
|
||||||
|
# A los que este usuarie tiene acceso
|
||||||
@posts = PostPolicy::Scope.new(current_usuarie, @posts).resolve
|
@posts = PostPolicy::Scope.new(current_usuarie, @posts).resolve
|
||||||
|
|
||||||
@category_name = if uuid?(@category)
|
|
||||||
@site.posts(lang: locale).find(@category, uuid: true)&.title&.value
|
|
||||||
else
|
|
||||||
@category
|
|
||||||
end
|
|
||||||
|
|
||||||
# Filtrar los posts que les invitades no pueden ver
|
# Filtrar los posts que les invitades no pueden ver
|
||||||
@usuarie = @site.usuarie? current_usuarie
|
@usuarie = @site.usuarie? current_usuarie
|
||||||
|
|
||||||
# Orden descendiente por número y luego por fecha
|
|
||||||
@posts.sort_by!(:order, :date).reverse!
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -169,4 +165,14 @@ class PostsController < ApplicationController
|
||||||
def forget_content
|
def forget_content
|
||||||
flash[:js] = { target: 'editor', action: 'forget-content', keys: (params[:storage_keys] || []).to_json }
|
flash[:js] = { target: 'editor', action: 'forget-content', keys: (params[:storage_keys] || []).to_json }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Los parámetros de filtros que vamos a mantener en todas las URLs,
|
||||||
|
# solo los que no estén vacíos.
|
||||||
|
#
|
||||||
|
# @return [Hash]
|
||||||
|
def filter_params
|
||||||
|
@filter_params ||= params.permit(:q, :category, :layout).to_h.select { |_,v| v.present? }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,6 +28,8 @@ class IndexedPost < ApplicationRecord
|
||||||
|
|
||||||
# Trae los IndexedPost en el orden en que van a terminar en el sitio.
|
# Trae los IndexedPost en el orden en que van a terminar en el sitio.
|
||||||
default_scope lambda { order(order: :desc, created_at: :desc) }
|
default_scope lambda { order(order: :desc, created_at: :desc) }
|
||||||
|
scope :in_category, lambda { |category| where("front_matter->'categories' ? :category", category: category.to_s) }
|
||||||
|
scope :by_usuarie, lambda { |usuarie| where("front_matter->'usuaries' @> :usuarie::jsonb", usuarie: usuarie.to_s) }
|
||||||
|
|
||||||
belongs_to :site
|
belongs_to :site
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Post
|
||||||
|
|
||||||
# Devuelve una versión indexable del Post
|
# Devuelve una versión indexable del Post
|
||||||
#
|
#
|
||||||
# @return [IndexedPosts]
|
# @return [IndexedPost]
|
||||||
def to_index
|
def to_index
|
||||||
IndexedPost.find_or_create_by(id: uuid.value).tap do |indexed_post|
|
IndexedPost.find_or_create_by(id: uuid.value).tap do |indexed_post|
|
||||||
indexed_post.layout = layout.name
|
indexed_post.layout = layout.name
|
||||||
|
@ -41,9 +41,16 @@ class Post
|
||||||
#
|
#
|
||||||
# @return [Hash]
|
# @return [Hash]
|
||||||
def indexable_front_matter
|
def indexable_front_matter
|
||||||
return {} unless attribute? :categories
|
{}.tap do |indexable_front_matter|
|
||||||
|
indexable_front_matter = {
|
||||||
|
usuaries: usuaries.map(&:id),
|
||||||
|
draft: attribute?(:draft) ? draft.value : false
|
||||||
|
}
|
||||||
|
|
||||||
{ categories: categories.indexable_values }
|
if attribute? :categories
|
||||||
|
indexable_front_matter[:categories] = categories.indexable_values
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Devuelve un documento indexable en texto plano
|
# Devuelve un documento indexable en texto plano
|
||||||
|
|
|
@ -59,9 +59,7 @@ class PostPolicy
|
||||||
def resolve
|
def resolve
|
||||||
return scope if scope&.first&.site&.usuarie? usuarie
|
return scope if scope&.first&.site&.usuarie? usuarie
|
||||||
|
|
||||||
scope.select do |post|
|
scope.by_usuarie(usuarie.id)
|
||||||
post.usuaries.include? usuarie
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
@site.name,
|
@site.name,
|
||||||
link_to(t('posts.index'),
|
link_to(t('posts.index'),
|
||||||
site_posts_path(@site)),
|
site_posts_path(@site)),
|
||||||
@category_name]
|
@category]
|
||||||
|
|
||||||
%main.row
|
%main.row
|
||||||
%aside.menu.col-md-3
|
%aside.menu.col-md-3
|
||||||
|
@ -14,15 +14,13 @@
|
||||||
%table.mb-3
|
%table.mb-3
|
||||||
- @site.layouts.each do |layout|
|
- @site.layouts.each do |layout|
|
||||||
- next if layout.hidden?
|
- next if layout.hidden?
|
||||||
- filter = params[:layout] == layout.value
|
|
||||||
%tr
|
%tr
|
||||||
%th= layout.humanized_name
|
%th= layout.humanized_name
|
||||||
%td.pl-3= link_to t('posts.add'),
|
%td.pl-3= link_to t('posts.add'), new_site_post_path(@site, **@filter_params), class: 'badge badge-secondary'
|
||||||
new_site_post_path(@site, layout: layout.name),
|
- if @filter_params[:layout] == layout.value
|
||||||
class: 'badge badge-secondary'
|
%td= link_to t('posts.remove_filter'), site_posts_path(@site, **@filter_params.merge(layout: nil)), class: 'badge badge-primary'
|
||||||
%td= link_to t(filter ? 'posts.remove_filter' : 'posts.filter'),
|
- else
|
||||||
site_posts_path(@site, layout: (filter ? nil : layout.value)),
|
%td= link_to t('posts.filter'), site_posts_path(@site, **@filter_params.merge(layout: layout.value)), class: 'badge badge-secondary'
|
||||||
class: 'badge badge-' + (filter ? 'primary' : 'secondary')
|
|
||||||
|
|
||||||
- if policy(@site).edit?
|
- if policy(@site).edit?
|
||||||
= link_to t('sites.edit.btn', site: @site.title), edit_site_path(@site), class: 'btn'
|
= link_to t('sites.edit.btn', site: @site.title), edit_site_path(@site), class: 'btn'
|
||||||
|
@ -48,19 +46,24 @@
|
||||||
|
|
||||||
%section.col
|
%section.col
|
||||||
= render 'layouts/flash'
|
= render 'layouts/flash'
|
||||||
|
.d-flex.justify-content-between.align-items-center.pl-2-plus.pr-2-plus.mb-2
|
||||||
|
%form
|
||||||
|
- @filter_params.each do |param, value|
|
||||||
|
- next if param == 'q'
|
||||||
|
%input{ type: 'input', name: param, value: value }
|
||||||
|
.form-group.flex-grow-0.m-0
|
||||||
|
%input.form-control.border.border-magenta{ type: 'search', placeholder: 'Buscar', name: 'q', value: @q }
|
||||||
|
%input.sr-only{ type: 'submit' }
|
||||||
|
- if @site.locales.size > 1
|
||||||
|
|
||||||
|
%nav#locales
|
||||||
|
- @site.locales.each do |locale|
|
||||||
|
= link_to t("locales.#{locale}.name"), site_posts_path(@site, **@filter_params.merge(locale: locale)),
|
||||||
|
class: "mr-2 mt-2 mb-2 #{locale == @locale ? 'active font-weight-bold' : ''}"
|
||||||
- if @posts.empty?
|
- if @posts.empty?
|
||||||
%h2= t('posts.none')
|
%h2= t('posts.empty')
|
||||||
- else
|
- else
|
||||||
= form_tag site_posts_reorder_path, method: :post do
|
= form_tag site_posts_reorder_path, method: :post do
|
||||||
.d-flex.justify-content-between.align-items-center
|
|
||||||
-#
|
|
||||||
TODO: Pensar una interfaz mejor para cuando haya más de tres
|
|
||||||
idiomas
|
|
||||||
- unless @site.locales.length == 1
|
|
||||||
.locales
|
|
||||||
- @site.locales.each do |locale|
|
|
||||||
= link_to t("locales.#{locale}.name"), site_posts_path(@site, locale: locale),
|
|
||||||
class: "mr-2 mt-2 mb-2#{locale == @locale ? 'active font-weight-bold' : ''}"
|
|
||||||
%table.table{ data: { controller: 'reorder' } }
|
%table.table{ data: { controller: 'reorder' } }
|
||||||
%caption.sr-only= t('posts.caption')
|
%caption.sr-only= t('posts.caption')
|
||||||
%thead
|
%thead
|
||||||
|
@ -76,6 +79,7 @@
|
||||||
%button.btn{ data: { action: 'reorder#bottom' } }= t('posts.reorder.bottom')
|
%button.btn{ data: { action: 'reorder#bottom' } }= t('posts.reorder.bottom')
|
||||||
%tbody
|
%tbody
|
||||||
- dir = t("locales.#{@locale}.dir")
|
- dir = t("locales.#{@locale}.dir")
|
||||||
|
- size = @posts.size
|
||||||
- @posts.each_with_index do |post, i|
|
- @posts.each_with_index do |post, i|
|
||||||
-#
|
-#
|
||||||
TODO: Solo les usuaries cachean porque tenemos que separar
|
TODO: Solo les usuaries cachean porque tenemos que separar
|
||||||
|
@ -84,45 +88,36 @@
|
||||||
TODO: Verificar qué pasa cuando se gestiona el sitio en
|
TODO: Verificar qué pasa cuando se gestiona el sitio en
|
||||||
distintos idiomas a la vez
|
distintos idiomas a la vez
|
||||||
- cache_if @usuarie, post do
|
- cache_if @usuarie, post do
|
||||||
- checkbox_id = "checkbox-#{post.uuid.value}"
|
- checkbox_id = "checkbox-#{post.id}"
|
||||||
%tr{ id: post.uuid.value, data: { target: 'reorder.row' } }
|
%tr{ id: post.id, data: { target: 'reorder.row' } }
|
||||||
%td
|
%td
|
||||||
.custom-control.custom-checkbox
|
.custom-control.custom-checkbox
|
||||||
%input.custom-control-input{ id: checkbox_id, type: 'checkbox', autocomplete: 'off', data: { action: 'reorder#select' } }
|
%input.custom-control-input{ id: checkbox_id, type: 'checkbox', autocomplete: 'off', data: { action: 'reorder#select' } }
|
||||||
%label.custom-control-label{ for: checkbox_id }
|
%label.custom-control-label{ for: checkbox_id }
|
||||||
%span.sr-only= t('posts.reorder.select')
|
%span.sr-only= t('posts.reorder.select')
|
||||||
-# Orden más alto es mayor prioridad
|
-# Orden más alto es mayor prioridad
|
||||||
= hidden_field 'post[reorder]', post.uuid.value,
|
= hidden_field 'post[reorder]', post.id,
|
||||||
value: @posts.length - i,
|
value: size - i,
|
||||||
data: { reorder: true }
|
data: { reorder: true }
|
||||||
%td.w-100{ class: dir }
|
%td.w-100{ class: dir }
|
||||||
= link_to site_post_path(@site, post.id) do
|
= link_to site_post_path(@site, post.path) do
|
||||||
%span{ lang: post.lang.value, dir: dir }= post.title.value
|
%span{ lang: post.locale, dir: dir }= post.title
|
||||||
- if post.attributes.include? :draft
|
- if post.front_matter['draft'].present?
|
||||||
- if post.draft.value
|
|
||||||
%span.badge.badge-primary
|
%span.badge.badge-primary
|
||||||
= post_label_t(:draft, post: post)
|
= post_label_t(:draft, post: post)
|
||||||
- if post.attributes.include? :categories
|
- if post.front_matter['categories'].present?
|
||||||
- unless post.categories.value.empty?
|
|
||||||
%br
|
%br
|
||||||
%small
|
%small
|
||||||
- (post.categories.respond_to?(:belongs_to) ? post.categories.belongs_to : post.categories.value).each do |c|
|
- post.front_matter['categories'].each do |category|
|
||||||
= link_to site_posts_path(@site, category: (c.respond_to?(:uuid) ? c.uuid.value : c)) do
|
= link_to site_posts_path(@site, **@filter_params.merge(category: category)) do
|
||||||
%span{ lang: post.lang.value, dir: dir }= (c.respond_to?(:title) ? c.title.value : c)
|
%span{ lang: post.locale, dir: dir }= category
|
||||||
|
|
||||||
%td
|
%td
|
||||||
= post.date.value.strftime('%F')
|
= post.created_at.strftime('%F')
|
||||||
%br/
|
%br/
|
||||||
- if post.attribute? :order
|
= post.order
|
||||||
= post.order.value
|
|
||||||
%td
|
%td
|
||||||
- if @usuarie || policy(post).edit?
|
- if @usuarie || policy(post).edit?
|
||||||
= link_to t('posts.edit'),
|
= link_to t('posts.edit'), edit_site_post_path(@site, post.path), class: 'btn btn-block'
|
||||||
edit_site_post_path(@site, post.id),
|
|
||||||
class: 'btn btn-block'
|
|
||||||
- if @usuarie || policy(post).destroy?
|
- if @usuarie || policy(post).destroy?
|
||||||
= link_to t('posts.destroy'),
|
= link_to t('posts.destroy'), site_post_path(@site, post.path), class: 'btn btn-block', method: :delete, data: { confirm: t('posts.confirm_destroy') }
|
||||||
site_post_path(@site, post.id),
|
|
||||||
class: 'btn btn-block',
|
|
||||||
method: :delete,
|
|
||||||
data: { confirm: t('posts.confirm_destroy') }
|
|
||||||
|
|
|
@ -397,6 +397,7 @@ en:
|
||||||
en: 'English'
|
en: 'English'
|
||||||
ar: 'Arabic'
|
ar: 'Arabic'
|
||||||
posts:
|
posts:
|
||||||
|
empty: "There are no results for those search parameters."
|
||||||
attribute_ro:
|
attribute_ro:
|
||||||
file:
|
file:
|
||||||
download: Download file
|
download: Download file
|
||||||
|
|
|
@ -459,6 +459,7 @@ es:
|
||||||
en: 'inglés'
|
en: 'inglés'
|
||||||
ar: 'árabe'
|
ar: 'árabe'
|
||||||
posts:
|
posts:
|
||||||
|
empty: No hay artículos con estos parámetros de búsqueda.
|
||||||
caption: Lista de artículos
|
caption: Lista de artículos
|
||||||
attribute_ro:
|
attribute_ro:
|
||||||
file:
|
file:
|
||||||
|
|
Loading…
Reference in a new issue