mirror of
https://0xacab.org/sutty/sutty
synced 2025-01-19 11:33:38 +00:00
nos habíamos olvidado que stimulus ya lo podía hacer solo
This commit is contained in:
parent
c04d4f1f7b
commit
207d1f6732
2 changed files with 113 additions and 97 deletions
|
@ -22,94 +22,9 @@ import { Controller } from 'stimulus'
|
||||||
* El objetivo es poder mover filas en tablas de miles de elementos.
|
* El objetivo es poder mover filas en tablas de miles de elementos.
|
||||||
*/
|
*/
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = [ 'row', 'unselect', 'top', 'bottom', 'direction', 'counter' ]
|
static targets = [ 'row', 'counter' ]
|
||||||
|
|
||||||
connect () {
|
connect () {
|
||||||
// Deseleccionar
|
|
||||||
this.unselectTarget.addEventListener('click', event => {
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
for (const r of Object.values(this.selected_rows)) {
|
|
||||||
r.row.querySelector('[data-reorder-handler]').click()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Enviar arriba de todo
|
|
||||||
this.topTarget.addEventListener('click', event => {
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
if (this.empty) return
|
|
||||||
|
|
||||||
const rows = this.sorted_rows()
|
|
||||||
const first = rows[0].row.parentElement.firstElementChild
|
|
||||||
|
|
||||||
for (const r of rows) {
|
|
||||||
const row = r.row
|
|
||||||
|
|
||||||
if (row === first) continue
|
|
||||||
|
|
||||||
row.parentElement.insertBefore(row, first)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reacomodamos el orden
|
|
||||||
this.reorder()
|
|
||||||
|
|
||||||
// Mantenemos el primero a la vista
|
|
||||||
rows[0].row.scrollIntoViewIfNeeded()
|
|
||||||
})
|
|
||||||
|
|
||||||
// Enviar al final
|
|
||||||
this.bottomTarget.addEventListener('click', event => {
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
if (this.empty) return
|
|
||||||
|
|
||||||
const rows = this.sorted_rows()
|
|
||||||
|
|
||||||
for (const r of rows) {
|
|
||||||
const row = r.row
|
|
||||||
|
|
||||||
row.parentElement.appendChild(row)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reacomodamos el orden
|
|
||||||
this.reorder()
|
|
||||||
|
|
||||||
// Mantenemos el primero a la vista
|
|
||||||
rows[0].row.scrollIntoViewIfNeeded()
|
|
||||||
})
|
|
||||||
|
|
||||||
this.rowTargets.forEach(row => {
|
|
||||||
// Al cambiar los inputs, mantener la lista de filas actualizadas.
|
|
||||||
// Necesitamos saber la posición para poder mover las filas en
|
|
||||||
// orden en lugar del orden en que fueron seleccionadas.
|
|
||||||
row.querySelector('[data-reorder-handler]').addEventListener('change', event => {
|
|
||||||
if (event.target.checked) {
|
|
||||||
this.selected_rows[row.id] = {
|
|
||||||
row,
|
|
||||||
order: this.rowTargets.indexOf(row)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
delete this.selected_rows[row.id]
|
|
||||||
}
|
|
||||||
|
|
||||||
this.counter()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
this.directionTargets.forEach(dir => {
|
|
||||||
dir.addEventListener('click', event => {
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
if (this.empty) return
|
|
||||||
|
|
||||||
this.move(dir.dataset.direction)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Lo asociamos al documento porque en la tabla se pierde el foco
|
// Lo asociamos al documento porque en la tabla se pierde el foco
|
||||||
// luego del primer evento.
|
// luego del primer evento.
|
||||||
document.addEventListener('keydown', event => {
|
document.addEventListener('keydown', event => {
|
||||||
|
@ -139,6 +54,13 @@ export default class extends Controller {
|
||||||
return (Object.keys(this.selected_rows).length === 0)
|
return (Object.keys(this.selected_rows).length === 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Las filas siempre ordenadas
|
||||||
|
*/
|
||||||
|
get sorted_rows () {
|
||||||
|
return Object.values(this.selected_rows).sort((a,b) => a.order - b.order)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Aplica el nuevo orden en las filas y sus campos
|
* Aplica el nuevo orden en las filas y sus campos
|
||||||
*/
|
*/
|
||||||
|
@ -154,10 +76,6 @@ export default class extends Controller {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
sorted_rows () {
|
|
||||||
return Object.values(this.selected_rows).sort((a,b) => a.order - b.order)
|
|
||||||
}
|
|
||||||
|
|
||||||
move (direction) {
|
move (direction) {
|
||||||
if (this.empty) return
|
if (this.empty) return
|
||||||
|
|
||||||
|
@ -166,7 +84,7 @@ export default class extends Controller {
|
||||||
const direction_sibling = up ? 'previousElementSibling' : 'nextElementSibling'
|
const direction_sibling = up ? 'previousElementSibling' : 'nextElementSibling'
|
||||||
|
|
||||||
// Los movemos en orden
|
// Los movemos en orden
|
||||||
const rows = this.sorted_rows()
|
const rows = this.sorted_rows
|
||||||
if (down) rows.reverse()
|
if (down) rows.reverse()
|
||||||
|
|
||||||
for (const r of rows) {
|
for (const r of rows) {
|
||||||
|
@ -193,4 +111,102 @@ export default class extends Controller {
|
||||||
counter () {
|
counter () {
|
||||||
this.counterTarget.innerText = Object.keys(this.selected_rows).length
|
this.counterTarget.innerText = Object.keys(this.selected_rows).length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deseleccionar todos
|
||||||
|
unselect (event) {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
|
||||||
|
for (const r of Object.values(this.selected_rows)) {
|
||||||
|
r.row.querySelector('[data-action="reorder#select"]').click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enviar arriba de todo
|
||||||
|
top (event) {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
|
||||||
|
if (this.empty) return
|
||||||
|
|
||||||
|
const rows = this.sorted_rows
|
||||||
|
const first = rows[0].row.parentElement.firstElementChild
|
||||||
|
|
||||||
|
for (const r of rows) {
|
||||||
|
const row = r.row
|
||||||
|
|
||||||
|
if (row === first) continue
|
||||||
|
|
||||||
|
row.parentElement.insertBefore(row, first)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reacomodamos el orden
|
||||||
|
this.reorder()
|
||||||
|
|
||||||
|
// Mantenemos el primero a la vista
|
||||||
|
rows[0].row.scrollIntoViewIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
bottom (event) {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
|
||||||
|
if (this.empty) return
|
||||||
|
|
||||||
|
const rows = this.sorted_rows
|
||||||
|
|
||||||
|
for (const r of rows) {
|
||||||
|
const row = r.row
|
||||||
|
|
||||||
|
row.parentElement.appendChild(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reacomodamos el orden
|
||||||
|
this.reorder()
|
||||||
|
|
||||||
|
// Mantenemos el primero a la vista
|
||||||
|
rows[0].row.scrollIntoViewIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Al cambiar los inputs, mantener la lista de filas actualizadas.
|
||||||
|
* Necesitamos saber la posición para poder mover las filas en orden
|
||||||
|
* en lugar del orden en que fueron seleccionadas.
|
||||||
|
*/
|
||||||
|
select (event) {
|
||||||
|
const row = event.target.closest('tr')
|
||||||
|
|
||||||
|
if (event.target.checked) {
|
||||||
|
this.selected_rows[row.id] = {
|
||||||
|
row,
|
||||||
|
order: this.rowTargets.indexOf(row)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
delete this.selected_rows[row.id]
|
||||||
|
}
|
||||||
|
|
||||||
|
this.counter()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mover hacia arriba
|
||||||
|
*/
|
||||||
|
up (event) {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
if (this.empty) return
|
||||||
|
|
||||||
|
this.move('up')
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mover hacia abajo
|
||||||
|
*/
|
||||||
|
down (event) {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
if (this.empty) return
|
||||||
|
|
||||||
|
this.move('down')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,13 +52,13 @@
|
||||||
%tr
|
%tr
|
||||||
%th.border-0.background-white.position-sticky{ style: 'top: 0', colspan: '4' }
|
%th.border-0.background-white.position-sticky{ style: 'top: 0', colspan: '4' }
|
||||||
= submit_tag t('posts.reorder.submit'), class: 'btn'
|
= submit_tag t('posts.reorder.submit'), class: 'btn'
|
||||||
%button.btn{ data: { target: 'reorder.unselect' } }
|
%button.btn{ data: { action: 'reorder#unselect' } }
|
||||||
= t('posts.reorder.unselect')
|
= t('posts.reorder.unselect')
|
||||||
%span.badge{ data: { target: 'reorder.counter' } } 0
|
%span.badge{ data: { target: 'reorder.counter' } } 0
|
||||||
%button.btn{ data: { target: 'reorder.direction', direction: 'up' } }= t('posts.reorder.up')
|
%button.btn{ data: { action: 'reorder#up' } }= t('posts.reorder.up')
|
||||||
%button.btn{ data: { target: 'reorder.direction', direction: 'down' } }= t('posts.reorder.down')
|
%button.btn{ data: { action: 'reorder#down' } }= t('posts.reorder.down')
|
||||||
%button.btn{ data: { target: 'reorder.top' } }= t('posts.reorder.top')
|
%button.btn{ data: { action: 'reorder#top' } }= t('posts.reorder.top')
|
||||||
%button.btn{ data: { target: '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")
|
||||||
- @posts.each_with_index do |post, i|
|
- @posts.each_with_index do |post, i|
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
- cache_if @usuarie, post do
|
- cache_if @usuarie, post do
|
||||||
%tr{ id: post.uuid.value, data: { target: 'reorder.row' } }
|
%tr{ id: post.uuid.value, data: { target: 'reorder.row' } }
|
||||||
%td
|
%td
|
||||||
%input{ type: 'checkbox', autocomplete: 'off', data: { reorder: { handler: true } } }
|
%input{ type: 'checkbox', autocomplete: 'off', data: { action: '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.uuid.value,
|
||||||
value: @posts.length - i,
|
value: @posts.length - i,
|
||||||
|
|
Loading…
Reference in a new issue