mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-23 01:06:22 +00:00
feat: pertenece a
This commit is contained in:
parent
105b2a1f1c
commit
c150acbd6f
8 changed files with 116 additions and 2 deletions
|
@ -126,7 +126,7 @@ class PostsController < ApplicationController
|
||||||
@uuid = @post.uuid.value
|
@uuid = @post.uuid.value
|
||||||
@name = params.require(:name)
|
@name = params.require(:name)
|
||||||
|
|
||||||
render 'posts/new_has_many_value', layout: false
|
render "posts/#{params.require(:attribute)}_value", layout: false
|
||||||
else
|
else
|
||||||
headers['HX-Retarget'] = "##{params.require(:form)}"
|
headers['HX-Retarget'] = "##{params.require(:form)}"
|
||||||
headers['HX-Reswap'] = 'outerHTML'
|
headers['HX-Reswap'] = 'outerHTML'
|
||||||
|
|
4
app/models/metadata_new_belongs_to.rb
Normal file
4
app/models/metadata_new_belongs_to.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Nueva interfaz
|
||||||
|
class MetadataNewBelongsTo < MetadataBelongsTo; end
|
|
@ -3,7 +3,7 @@
|
||||||
checkbox_attributes = local_assigns.slice(:id, :type, :name, :value, :required, :checked)
|
checkbox_attributes = local_assigns.slice(:id, :type, :name, :value, :required, :checked)
|
||||||
checkbox_attributes[:type] ||= 'checkbox'
|
checkbox_attributes[:type] ||= 'checkbox'
|
||||||
|
|
||||||
.custom-control.custom-checkbox
|
.custom-control{ class: "custom-#{checkbox_attributes[:type]}" }
|
||||||
%input.custom-control-input{ **checkbox_attributes }
|
%input.custom-control-input{ **checkbox_attributes }
|
||||||
%label.custom-control-label{ for: id, aria: { describedby: help_id } }= content
|
%label.custom-control-label{ for: id, aria: { describedby: help_id } }= content
|
||||||
- if (block = yield).present?
|
- if (block = yield).present?
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
%input{ type: 'hidden', name: 'form', value: options[:id] }
|
%input{ type: 'hidden', name: 'form', value: options[:id] }
|
||||||
%input{ type: 'hidden', name: 'dir', value: dir }
|
%input{ type: 'hidden', name: 'dir', value: dir }
|
||||||
%input{ type: 'hidden', name: 'locale', value: locale }
|
%input{ type: 'hidden', name: 'locale', value: locale }
|
||||||
|
%input{ type: 'hidden', name: 'attribute', value: params.require(:attribute) }
|
||||||
%input{ type: 'hidden', name: 'target', value: params.require(:target) }
|
%input{ type: 'hidden', name: 'target', value: params.require(:target) }
|
||||||
%input{ type: 'hidden', name: 'swap', value: params.require(:swap) }
|
%input{ type: 'hidden', name: 'swap', value: params.require(:swap) }
|
||||||
- if params[:inverse].present?
|
- if params[:inverse].present?
|
||||||
|
|
6
app/views/posts/attribute_ro/_new_belongs_to.haml
Normal file
6
app/views/posts/attribute_ro/_new_belongs_to.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
%tr{ id: attribute }
|
||||||
|
%th= post_label_t(attribute, post: post)
|
||||||
|
%td{ dir: dir, lang: locale }
|
||||||
|
- p = metadata.belongs_to
|
||||||
|
- if p
|
||||||
|
= link_to p.title.value, site_post_path(site, p.id)
|
100
app/views/posts/attributes/_new_belongs_to.haml
Normal file
100
app/views/posts/attributes/_new_belongs_to.haml
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
-#
|
||||||
|
Genera un listado de radios entre los que se puede elegir solo uno para
|
||||||
|
guardar. Podemos elegir entre los artículos ya cargados o agregar uno
|
||||||
|
nuevo.
|
||||||
|
|
||||||
|
Al agregar uno nuevo, se abre un segundo modal que carga el formulario
|
||||||
|
correspondiente vía HTMX. El formulario tiene que cargarse por fuera
|
||||||
|
del formulario principal porque no se pueden anidar.
|
||||||
|
|
||||||
|
:ruby
|
||||||
|
id = id_for(base, attribute)
|
||||||
|
name = "#{base}[#{attribute}]"
|
||||||
|
form_id = "form-#{Nanoid.generate}"
|
||||||
|
modal_id = "modal-#{Nanoid.generate}"
|
||||||
|
post_id = "post-#{Nanoid.generate}"
|
||||||
|
post_form_id = "post-form-#{Nanoid.generate}"
|
||||||
|
post_modal_id = "post-modal-#{Nanoid.generate}"
|
||||||
|
post_form_loaded_id = "post-loaded-#{Nanoid.generate}"
|
||||||
|
value_list_id = "#{id}_body"
|
||||||
|
|
||||||
|
%div{ id: modal_id, data: { controller: 'modal array', 'array-original-value': metadata.value.to_json, 'array-new-array-value': site_posts_new_related_post_path(site) } }
|
||||||
|
.form-group
|
||||||
|
= hidden_field_tag name, ''
|
||||||
|
= label_tag id, post_label_t(attribute, post: post)
|
||||||
|
-# Mostramos la lista de valores actuales.
|
||||||
|
|
||||||
|
Al aceptar el modal, se vacía el listado y se completa en base a
|
||||||
|
renderizaciones con HTMX. Para poder hacer eso, tenemos que poder
|
||||||
|
acceder a todos los items dentro del modal (como array.item) y
|
||||||
|
enviar el valor al endpoint que devuelve uno por uno. Esto lo
|
||||||
|
tenemos disponible en Stimulus, pero queremos usar HTMX o técnica
|
||||||
|
similar para poder renderizar del lado del servidor.
|
||||||
|
|
||||||
|
Para poder cancelar, mantenemos el estado original y desactivamos
|
||||||
|
o activamos los ítemes según estén incluidos en esa lista o no.
|
||||||
|
.row.row-cols-3.row-cols-md-4{ data: { target: 'array.current' } }
|
||||||
|
- metadata.values.slice(*metadata.value).each do |value|
|
||||||
|
= render 'posts/new_array_value', value: value
|
||||||
|
|
||||||
|
= render 'bootstrap/btn', content: t('.edit'), action: 'modal#show'
|
||||||
|
|
||||||
|
= render 'bootstrap/modal', id: id, modal_content_attributes: { class: 'h-100' }, hide_actions: ['array#cancel'] do
|
||||||
|
- content_for :"#{id}_header" do
|
||||||
|
.form-group.flex-grow-1.mb-0
|
||||||
|
= label_tag id, post_label_t(attribute, post: post)
|
||||||
|
%input.form-control{ data: { target: 'array.search', action: 'input->array#search' }, type: 'search', placeholder: t('.filter') }
|
||||||
|
|
||||||
|
- content_for :"#{id}_body" do
|
||||||
|
.form-group.mb-0{ id: value_list_id }
|
||||||
|
- metadata.values.each_pair do |value, uuid|
|
||||||
|
.mb-2{ data: { target: 'array.item', 'searchable-value': value.remove_diacritics.downcase, value: uuid } }
|
||||||
|
= render 'bootstrap/custom_checkbox', name: name, id: "value-#{Nanoid.generate}", value: uuid, checked: metadata.value.include?(uuid), content: value, type: 'radio'
|
||||||
|
|
||||||
|
-#
|
||||||
|
Según la definición del campo, si hay un filtro, tenemos que poder
|
||||||
|
elegir qué tipo de esquema queremos o si hay uno solo, siempre
|
||||||
|
vamos a enviar ese. Si no hay ninguno, tendríamos que poder elegir
|
||||||
|
entre todos los esquemas.
|
||||||
|
|
||||||
|
- content_for :"#{id}_footer" do
|
||||||
|
- layout = metadata.filter[:layout]
|
||||||
|
- if layout.is_a?(String)
|
||||||
|
%input{ type: 'hidden', name: 'layout', value: layout, form: post_form_id }
|
||||||
|
= render 'bootstrap/btn', content: t('.add', layout: site.layouts[layout].humanized_name), form: post_form_id, type: 'submit', class: 'm-0 mr-1'
|
||||||
|
- else
|
||||||
|
- layouts = layout&.map { |x| site.layouts[x] }
|
||||||
|
- layouts ||= site.layouts.values
|
||||||
|
.input-group.w-auto.flex-grow-1.my-0
|
||||||
|
%select.form-control{ form: post_form_id, name: 'layout' }
|
||||||
|
- layouts.each do |layout|
|
||||||
|
%option{ value: layout.name }= layout.humanized_name
|
||||||
|
.input-group-append
|
||||||
|
= render 'bootstrap/btn', content: t('.add', layout: ''), form: post_form_id, type: 'submit', class: 'mb-0 mr-0'
|
||||||
|
= render 'bootstrap/btn', content: t('.accept'), action: 'array#accept modal#hide', class: 'm-0 mr-1'
|
||||||
|
= render 'bootstrap/btn', content: t('.cancel'), action: 'array#cancel modal#hide', class: 'm-0'
|
||||||
|
|
||||||
|
-#
|
||||||
|
Este segundo modal es el que carga los formularios de
|
||||||
|
creación/modificación de artículos relacionados. Se envía a post_form
|
||||||
|
para que sea externo al formulario actual.
|
||||||
|
- content_for :post_form do
|
||||||
|
%form{ id: post_form_id, 'hx-get': site_posts_form_path(site), 'hx-target': "##{post_form_loaded_id}" }
|
||||||
|
%input{ type: 'hidden', name: 'show', value: post_modal_id }
|
||||||
|
%input{ type: 'hidden', name: 'hide', value: modal_id }
|
||||||
|
%input{ type: 'hidden', name: 'target', value: value_list_id }
|
||||||
|
%input{ type: 'hidden', name: 'swap', value: 'beforeend' }
|
||||||
|
%input{ type: 'hidden', name: 'base', value: id }
|
||||||
|
%input{ type: 'hidden', name: 'name', value: name }
|
||||||
|
%input{ type: 'hidden', name: 'form', value: form_id }
|
||||||
|
%input{ type: 'hidden', name: 'attribute', value: metadata.type }
|
||||||
|
- if metadata.inverse?
|
||||||
|
%input{ type: 'hidden', name: 'inverse', value: metadata.inverse }
|
||||||
|
%div{ id: post_modal_id, data: { controller: 'modal' } }
|
||||||
|
= render 'bootstrap/modal', id: post_id, modal_content_attributes: { class: 'h-100' } do
|
||||||
|
- content_for :"#{post_id}_body" do
|
||||||
|
%div{ id: post_form_loaded_id }
|
||||||
|
- content_for :"#{post_id}_footer" do
|
||||||
|
= render 'bootstrap/btn', form: form_id, content: t('.save'), type: 'submit'
|
||||||
|
-# @todo: Volver al otro modal
|
||||||
|
= render 'bootstrap/btn', content: t('.cancel'), action: 'modal#hide'
|
|
@ -87,6 +87,7 @@
|
||||||
%input{ type: 'hidden', name: 'base', value: id }
|
%input{ type: 'hidden', name: 'base', value: id }
|
||||||
%input{ type: 'hidden', name: 'name', value: name }
|
%input{ type: 'hidden', name: 'name', value: name }
|
||||||
%input{ type: 'hidden', name: 'form', value: form_id }
|
%input{ type: 'hidden', name: 'form', value: form_id }
|
||||||
|
%input{ type: 'hidden', name: 'attribute', value: metadata.type }
|
||||||
- if metadata.inverse?
|
- if metadata.inverse?
|
||||||
%input{ type: 'hidden', name: 'inverse', value: metadata.inverse }
|
%input{ type: 'hidden', name: 'inverse', value: metadata.inverse }
|
||||||
%div{ id: post_modal_id, data: { controller: 'modal' } }
|
%div{ id: post_modal_id, data: { controller: 'modal' } }
|
||||||
|
|
2
app/views/posts/new_belongs_to_value.haml
Normal file
2
app/views/posts/new_belongs_to_value.haml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.mb-2{ data: { target: 'array.item', 'searchable-value': @value.remove_diacritics.downcase, value: @uuid } }
|
||||||
|
= render 'bootstrap/custom_checkbox', name: @name, id: "value-#{Nanoid.generate}", value: @uuid, checked: true, content: @value, type: 'radio'
|
Loading…
Reference in a new issue