Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Display additional fields when attaching a record to another #3048

Merged
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
670ba0a
add fields
binarygit Jul 30, 2024
f79177e
Apply options like update_using when attaching record
binarygit Jul 31, 2024
689d72a
Lint
binarygit Jul 31, 2024
c7ae36c
Use keyword arguments
binarygit Jul 31, 2024
fd1f441
Ensure through attachments without additional params are correctly at…
binarygit Jul 31, 2024
f6cfb9e
Refactor: use fill_record method itself
binarygit Jul 31, 2024
a60de9f
Refactor: do not send redundant args to fieldsexecContext
binarygit Jul 31, 2024
abdd39d
Add translation key
binarygit Jul 31, 2024
37f9c60
Refactor: use @reflection and remove duplication
binarygit Jul 31, 2024
b6b0e85
Use extra_fields instead of extra
binarygit Jul 31, 2024
31dd758
Update app/controllers/avo/associations_controller.rb
binarygit Jul 31, 2024
77e2988
Merge branch 'main' into display-additional-columns-in-join-records
Paul-Bob Jul 31, 2024
cfd4090
wip styling
adrianthedev Aug 1, 2024
ec2f378
include blank on the select
binarygit Aug 1, 2024
109e0f7
Do not pass in nil value for model because it is deprecated
binarygit Aug 1, 2024
30f37cb
Remove duplicate key
binarygit Aug 1, 2024
950a88e
Format
binarygit Aug 1, 2024
78bbb18
Give clear name
binarygit Aug 1, 2024
7e909a1
Update app/controllers/avo/associations_controller.rb
binarygit Aug 1, 2024
73d8829
Rename to attach_fields
binarygit Aug 1, 2024
1993546
Merge branch 'main' into display-additional-columns-in-join-records
Paul-Bob Aug 2, 2024
1a1ec9e
Merge branch 'main' into display-additional-columns-in-join-records
Paul-Bob Aug 2, 2024
6751d8a
Display correct label
binarygit Aug 5, 2024
a748541
Enable additional fields when select is searchable
binarygit Aug 5, 2024
8d057bf
Lint
binarygit Aug 5, 2024
4412710
Add label_text
binarygit Aug 5, 2024
edc6f5a
Merge branch 'main' into display-additional-columns-in-join-records
Paul-Bob Aug 5, 2024
76a01ff
Fix indentation
binarygit Aug 5, 2024
90a64f9
Change texts to reflect the association
binarygit Aug 5, 2024
19d5da0
Fix tests
binarygit Aug 5, 2024
c2aed1b
Fix feature test
binarygit Aug 5, 2024
76a7cc2
Refactor associations controller and display sigularized field names
binarygit Aug 5, 2024
12c96e8
Remove useless assignment
binarygit Aug 5, 2024
981ecee
Update app/controllers/avo/associations_controller.rb
Paul-Bob Aug 5, 2024
c1a463a
Update app/controllers/avo/associations_controller.rb
Paul-Bob Aug 5, 2024
a40e604
Update app/views/avo/associations/new.html.erb
Paul-Bob Aug 5, 2024
83ffa20
Update app/views/avo/associations/new.html.erb
Paul-Bob Aug 5, 2024
0a8a670
Update spec/system/avo/for_attribute_spec.rb
Paul-Bob Aug 5, 2024
8ce929d
Update app/controllers/avo/associations_controller.rb
Paul-Bob Aug 5, 2024
4763aac
field_wrapper on searchable
Paul-Bob Aug 5, 2024
e16142b
Merge branch 'main' into display-additional-columns-in-join-records
Paul-Bob Aug 5, 2024
a00b433
Update app/controllers/avo/associations_controller.rb
Paul-Bob Aug 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions app/controllers/avo/associations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class AssociationsController < BaseController
before_action :set_attachment_class, only: [:show, :index, :new, :create, :destroy]
before_action :set_attachment_resource, only: [:show, :index, :new, :create, :destroy]
before_action :set_attachment_record, only: [:create, :destroy]
before_action :set_attach_fields, only: [:new, :create]
before_action :authorize_index_action, only: :index
before_action :authorize_attach_action, only: :new
before_action :authorize_detach_action, only: :destroy
Expand Down Expand Up @@ -67,6 +68,7 @@ def create
notice: t("avo.attachment_class_attached", attachment_class: @related_resource.name)
}
else
flash[:error] = t("avo.attachment_failed", attachment_class: @related_resource.name)
format.turbo_stream {
render turbo_stream: turbo_stream.append("alerts", partial: "avo/partials/all_alerts")
}
Expand All @@ -78,7 +80,9 @@ def create_association
association_name = BaseResource.valid_association_name(@record, association_from_params)

perform_action_and_record_errors do
if has_many_reflection?
if through_reflection? && additional_params.present?
new_join_record.save
elsif has_many_reflection? || through_reflection?
@record.send(association_name) << @attachment_record
else
@record.send(:"#{association_name}=", @attachment_record)
Expand All @@ -90,7 +94,7 @@ def create_association
def destroy
association_name = BaseResource.valid_association_name(@record, @field.for_attribute || params[:related_name])

if @reflection.instance_of? ActiveRecord::Reflection::ThroughReflection
if through_reflection?
join_record.destroy!
elsif has_many_reflection?
@record.send(association_name).delete @attachment_record
Expand Down Expand Up @@ -190,5 +194,36 @@ def has_many_reflection?
ActiveRecord::Reflection::HasAndBelongsToManyReflection
]
end

def through_reflection?
@reflection.instance_of? ActiveRecord::Reflection::ThroughReflection
end

def additional_params
params[:fields].permit(@attach_fields&.map(&:id))
Paul-Bob marked this conversation as resolved.
Show resolved Hide resolved
end

def set_attach_fields
@attach_fields = if @field.attach_fields.present?
Avo::FieldsExecutionContext.new(target: @field.attach_fields)
.detect_fields
.items_holder
.items
end
end

def new_join_record
@resource.fill_record(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adrianthedev We use fill_record which permits and assigns only those values whose key match the fields declared by the user in their resources file. I think this mitigates the chances of such attacks, no?

def fill_record(record, params, extra_params: [], fields: nil)

Copy link
Contributor

@Paul-Bob Paul-Bob Aug 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this mitigates the chances of such attacks, no?

Yes, but let's apply the permit directly inside the additional_params method to increase readability.

def additional_params
  params[:fields].permit(@attach_fields.map(&:id))
end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okayy. Got it 😄

@reflection.through_reflection.klass.new,
additional_params.merge(
{
source_foreign_key => @attachment_record.id,
through_foreign_key => @record.id
}
),
fields: @attach_fields,
extra_params: [source_foreign_key, through_foreign_key]
)
end
end
end
65 changes: 45 additions & 20 deletions app/views/avo/associations/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,56 @@
} do |form| %>
<%= render Avo::ModalComponent.new do |c| %>
<% c.with_heading do %>
<%= t 'avo.choose_item', item: @related_resource.name.downcase %>
<%= t 'avo.choose_item', item: @field.name.singularize.downcase %>
<% end %>

<div class="flex-1 flex items-center justify-center px-0 lg:px-8 text-lg mt-8 mb-12">
<% if @field.is_searchable? %>
<%= render Avo::Pro::SearchableAssociations::AutocompleteComponent.new form: form,
classes: input_classes("w-full"),
field: @field,
model_key: @field.target_resource&.model_key,
foreign_key: 'related_id',
resource: @resource,
view: :new
%>
<% else %>
<div class="flex-1 flex flex-col items-center justify-center px-0 md:px-24 text-base">
<%= form.select :related_id, options_for_select(@options, nil),
{
<div class="flex-1 flex flex-col items-center justify-center px-0 md:px-24 text-base">
<div class="w-full">
<% if @field.is_searchable? %>
<%= field_wrapper stacked: true,
field: @field,
view: Avo::ViewInquirer.new("edit"),
form:,
index: 0,
resource: @resource,
label_for: @field.id,
label: @field.name.singularize.downcase do %>
<%= render Avo::Pro::SearchableAssociations::AutocompleteComponent.new form: form,
classes: input_classes("w-full"),
field: @field,
model_key: @field.target_resource&.model_key,
foreign_key: 'related_id',
resource: @resource,
view: :new
%>
<% end %>
<% else %>
<%= avo_edit_field :related_id,
as: :select,
form: form,
name: @field.name.singularize,
options: options_for_select(@options,
nil),
include_blank: t('avo.choose_an_option'),
},
{
class: input_classes('w-full'),
}
%>
stacked: true,
classes: 'w-full'
%>
<% end %>
<% @attach_fields&.each_with_index do |field, index| %>
<%= render(Avo::Items::SwitcherComponent.new(
resource: @related_resource,
item: field,
index: index + 1,
view: @view,
form: form,
field_component_extra_args: {
stacked: true,
classes: 'w-full'}
)) %>
<% end %>
</div>
<% end %>
</div>
</div>

<% c.with_controls do %>
Expand Down
2 changes: 1 addition & 1 deletion lib/avo/fields/base_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def to_permitted_param
end

def record_errors
record.nil? ? {} : record.errors
record.present? ? record.errors : {}
end

def type
Expand Down
2 changes: 1 addition & 1 deletion lib/avo/fields/concerns/is_required.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def is_required?
private

def required_from_validators
return false if record.nil?
return false unless record.present?

validators.any? do |validator|
validator.is_a? ActiveModel::Validations::PresenceValidator
Expand Down
2 changes: 2 additions & 0 deletions lib/avo/fields/has_base_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class HasBaseField < BaseField
attr_accessor :discreet_pagination
attr_accessor :hide_search_input
attr_reader :link_to_child_resource
attr_reader :attach_fields

def initialize(id, **args, &block)
super(id, **args, &block)
Expand All @@ -27,6 +28,7 @@ def initialize(id, **args, &block)
@link_to_child_resource = args[:link_to_child_resource] || false
@reloadable = args[:reloadable].present? ? args[:reloadable] : false
@linkable = args[:linkable].present? ? args[:linkable] : false
@attach_fields = args[:attach_fields]
end

def field_resource
Expand Down
13 changes: 13 additions & 0 deletions lib/avo/fields_execution_context.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module Avo
class FieldsExecutionContext < Avo::ExecutionContext
include Avo::Concerns::HasItems

def detect_fields
self.items_holder = Avo::Resources::Items::Holder.new(parent: self)

instance_exec(&target) if target.present? && target.respond_to?(:call)

self
end
end
end
38 changes: 22 additions & 16 deletions lib/avo/resources/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,14 +285,16 @@ def detect_fields
self
end

VIEW_METHODS_MAPPING = {
index: [:index_fields, :display_fields],
show: [:show_fields, :display_fields],
edit: [:edit_fields, :form_fields],
update: [:edit_fields, :form_fields],
new: [:new_fields, :form_fields],
create: [:new_fields, :form_fields]
} unless defined? VIEW_METHODS_MAPPING
unless defined? VIEW_METHODS_MAPPING
VIEW_METHODS_MAPPING = {
index: [:index_fields, :display_fields],
show: [:show_fields, :display_fields],
edit: [:edit_fields, :form_fields],
update: [:edit_fields, :form_fields],
new: [:new_fields, :form_fields],
create: [:new_fields, :form_fields]
}
end

def fetch_fields
possible_methods_for_view = VIEW_METHODS_MAPPING[view.to_sym]
Expand Down Expand Up @@ -334,12 +336,12 @@ def divider(label = nil)
end

# def get_actions / def get_filters / def get_scopes
define_method "get_#{plural_entity}" do
define_method :"get_#{plural_entity}" do
return entity_loader(entity).bag if entity_loader(entity).present?

# ex: @actions_loader = Avo::Loaders::ActionsLoader.new
instance_variable_set(
"@#{plural_entity}_loader",
:"@#{plural_entity}_loader",
"Avo::Loaders::#{plural_entity.humanize}Loader".constantize.new
)

Expand All @@ -349,8 +351,8 @@ def divider(label = nil)
end

# def get_action_arguments / def get_filter_arguments / def get_scope_arguments
define_method "get_#{entity}_arguments" do |entity_class|
klass = send("get_#{plural_entity}").find { |entity| entity[:class].to_s == entity_class.to_s }
define_method :"get_#{entity}_arguments" do |entity_class|
klass = send(:"get_#{plural_entity}").find { |entity| entity[:class].to_s == entity_class.to_s }

raise "Couldn't find '#{entity_class}' in the 'def #{plural_entity}' method on your '#{self.class}' resource." if klass.nil?

Expand All @@ -359,7 +361,7 @@ def divider(label = nil)
end

def hydrate(...)
super(...)
super
binarygit marked this conversation as resolved.
Show resolved Hide resolved
binarygit marked this conversation as resolved.
Show resolved Hide resolved

if @record.present?
hydrate_model_with_default_values if @view&.new?
Expand Down Expand Up @@ -443,10 +445,14 @@ def fields_by_database_id
.to_h
end

def fill_record(record, params, extra_params: [])
def fill_record(record, params, extra_params: [], fields: nil)
# Write the field values
params.each do |key, value|
field = fields_by_database_id[key]
field = if fields.present?
fields.find { |f| f.id == key.to_sym }
else
fields_by_database_id[key]
end

next unless field.present?

Expand Down Expand Up @@ -601,7 +607,7 @@ def description_attributes
end

def entity_loader(entity)
instance_variable_get("@#{entity.to_s.pluralize}_loader")
instance_variable_get(:"@#{entity.to_s.pluralize}_loader")
end

def record_param
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.ar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ ar:
attachment_class_attached: "%{attachment_class} تم ربط"
attachment_class_detached: "%{attachment_class} تم فصل"
attachment_destroyed: تم حذف المرفق
attachment_failed: فشل في إرفاق %{attachment_class}
cancel: إلغاء
choose_a_country: اختر دولة
choose_an_option: اختر خيارًا
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ de:
attach_item: "%{item} anhängen"
attachment_class_attached: "%{attachment_class} angehängt."
attachment_class_detached: "%{attachment_class} abgehängt."
attachment_failed: "Kon %{attachment_class} niet bijvoegen"
attachment_destroyed: Anhang gelöscht
cancel: Abbrechen
choose_a_country: Land auswählen
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ en:
attachment_class_attached: "%{attachment_class} attached."
attachment_class_detached: "%{attachment_class} detached."
attachment_destroyed: Attachment destroyed
attachment_failed: Failed to attach %{attachment_class}
cancel: Cancel
choose_a_country: Choose a country
choose_an_option: Choose an option
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ es:
attachment_class_attached: "%{attachment_class} adjuntado/a."
attachment_class_detached: "%{attachment_class} adjuntado/a."
attachment_destroyed: Adjunto eliminado
attachment_failed: No se pudo adjuntar %{attachment_class}
cancel: Cancelar
choose_a_country: Elige un país
choose_an_option: Elige una opción
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ fr:
attachment_class_attached: "%{attachment_class} attaché."
attachment_class_detached: "%{attachment_class} détaché."
attachment_destroyed: Pièce jointe détruite
attachment_failed: Échec de l'ajout de %{attachment_class}
cancel: Annuler
choose_a_country: Sélectionnez un pays
choose_an_option: Sélectionnez une option
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.it.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ it:
attach_item: Allega %{item}
attachment_class_attached: "%{attachment_class} allegato."
attachment_class_detached: "%{attachment_class} staccato."
attachment_failed: "Impossibile allegare %{attachment_class}"
attachment_destroyed: Allegato distrutto
cancel: Annulla
choose_a_country: Scegli un paese
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ ja:
attachment_class_attached: "%{attachment_class}をアタッチしました。"
attachment_class_detached: "%{attachment_class}をデタッチしました。"
attachment_destroyed: アタッチは削除されました
attachment_failed: "%{attachment_class}の添付に失敗しました"
cancel: キャンセル
choose_a_country: 国を選択
choose_an_option: オプションを選択
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.nb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ nb:
attachment_class_attached: "%{attachment_class} lagt til."
attachment_class_detached: "%{attachment_class} fjernet."
attachment_destroyed: Vedlett slettet
attachment_failed: Kunne ikke legge ved %{attachment_class}
cancel: Avbryt
choose_a_country: Velg et land
choose_an_option: Velg et alternativ
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.nl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ nl:
attach_item: "%{item} bijvoegen"
attachment_class_attached: "%{attachment_class} bijgevoegd."
attachment_class_detached: "%{attachment_class} losgekoppeld."
attachment_failed: "Kon %{attachment_class} niet bijvoegen"
attachment_destroyed: Bijlage verwijderd
cancel: Annuleren
choose_a_country: Kies een land
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.nn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ nn:
attachment_class_attached: "%{attachment_class} lagt til."
attachment_class_detached: "%{attachment_class} fjerna."
attachment_destroyed: Vedlegg sletta
attachment_failed: Klarte ikkje å legge ved %{attachment_class}
cancel: Avbryt
choose_a_country: Vel eit land
choose_an_option: Vel eit alternativ
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.pl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pl:
attach_item: Załącz %{item}
attachment_class_attached: "%{attachment_class} załączony."
attachment_class_detached: "%{attachment_class} odłączony."
attachment_failed: "Nie udało się dołączyć %{attachment_class}"
attachment_destroyed: Załącznik usunięty
cancel: Anuluj
choose_a_country: Wybierz kraj
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.pt-BR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pt-BR:
attachment_class_attached: "%{attachment_class} anexado."
attachment_class_detached: "%{attachment_class} separado."
attachment_destroyed: Anexo destruído
attachment_failed: Não foi possível anexar %{attachment_class}
cancel: Cancelar
choose_a_country: Escolha um país
choose_an_option: Escolha uma opção
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.pt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pt:
attachment_class_attached: "%{attachment_class} anexado."
attachment_class_detached: "%{attachment_class} separado."
attachment_destroyed: Anexo destruído
attachment_failed: Não foi possível anexar %{attachment_class}
cancel: Cancelar
choose_a_country: Escolha um país
choose_an_option: Escolha uma opção
Expand Down
1 change: 1 addition & 0 deletions lib/generators/avo/templates/locales/avo.ro.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ ro:
attachment_class_attached: "%{attachment_class} anexat."
attachment_class_detached: "%{attachment_class} separat."
attachment_destroyed: Atașamentul a fost distrus
attachment_failed: Nu s-a reușit atașarea %{attachment_class}
cancel: Anulează
choose_a_country: Alege o țară
choose_an_option: Alege o opțiune
Expand Down
Loading
Loading